Skip to content

Commit 2ed1ba2

Browse files
committed
Iterate through a broken Series
1 parent b41a44b commit 2ed1ba2

File tree

4 files changed

+63
-27
lines changed

4 files changed

+63
-27
lines changed

src/Iteration.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,15 @@ AdvanceStatus Iteration::beginStep(bool reread)
595595
auto newType =
596596
const_cast<Access *>(&this->IOHandler()->m_frontendAccess);
597597
*newType = Access::READ_WRITE;
598-
series.readGorVBased(false);
598+
try
599+
{
600+
series.readGorVBased(false);
601+
}
602+
catch (...)
603+
{
604+
*newType = oldType;
605+
throw;
606+
}
599607
*newType = oldType;
600608
series.iterations.written() = previous;
601609
}

src/ReadIterations.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ SeriesIterator &SeriesIterator::operator++()
117117
std::cerr << "[SeriesIterator] Cannot read iteration due to error "
118118
"below, will skip it.\n"
119119
<< err.what() << std::endl;
120+
// Need to close the current step manually because there is no
121+
// iteration to close
122+
Parameter<Operation::ADVANCE> param;
123+
param.mode = AdvanceMode::ENDSTEP;
124+
series.IOHandler()->enqueue(IOTask(&series, std::move(param)));
125+
series.IOHandler()->flush({FlushLevel::UserFlush});
120126
return operator++();
121127
}
122128
if (status == AdvanceStatus::OVER)

src/Series.cpp

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -510,21 +510,30 @@ Given file pattern: ')END"
510510
auto newType = const_cast<Access *>(&IOHandler()->m_frontendAccess);
511511
*newType = Access::READ_WRITE;
512512

513-
if (input->iterationEncoding == IterationEncoding::fileBased)
514-
readFileBased();
515-
else
516-
readGorVBased();
517-
518-
if (series.iterations.empty())
513+
try
519514
{
520-
/* Access::READ_WRITE can be used to create a new Series
521-
* allow setting attributes in that case */
522-
written() = false;
523515

524-
initDefaults(input->iterationEncoding);
525-
setIterationEncoding(input->iterationEncoding);
516+
if (input->iterationEncoding == IterationEncoding::fileBased)
517+
readFileBased();
518+
else
519+
readGorVBased();
526520

527-
written() = true;
521+
if (series.iterations.empty())
522+
{
523+
/* Access::READ_WRITE can be used to create a new Series
524+
* allow setting attributes in that case */
525+
written() = false;
526+
527+
initDefaults(input->iterationEncoding);
528+
setIterationEncoding(input->iterationEncoding);
529+
530+
written() = true;
531+
}
532+
}
533+
catch (...)
534+
{
535+
*newType = oldType;
536+
throw;
528537
}
529538

530539
*newType = oldType;
@@ -1100,13 +1109,14 @@ void Series::readGorVBased(bool do_init)
11001109
IOHandler()->flush(internal::defaultFlushParams);
11011110

11021111
/*
1103-
* Return true when iteration is parsed successfully.
1112+
* Return error if one is caught.
11041113
*/
1105-
auto readSingleIteration = [&series, &pOpen, this](
1106-
uint64_t index,
1107-
std::string path,
1108-
bool guardAgainstRereading,
1109-
bool beginStep) -> bool {
1114+
auto readSingleIteration =
1115+
[&series, &pOpen, this](
1116+
uint64_t index,
1117+
std::string path,
1118+
bool guardAgainstRereading,
1119+
bool beginStep) -> std::optional<error::ReadError> {
11101120
if (series.iterations.contains(index))
11111121
{
11121122
// maybe re-read
@@ -1115,7 +1125,7 @@ void Series::readGorVBased(bool do_init)
11151125
// reparsing is not needed
11161126
if (guardAgainstRereading && i.written())
11171127
{
1118-
return true;
1128+
return {};
11191129
}
11201130
if (i.get().m_closed != internal::CloseStatus::ParseAccessDeferred)
11211131
{
@@ -1142,7 +1152,7 @@ void Series::readGorVBased(bool do_init)
11421152
<< "' and will skip it due to read error:\n"
11431153
<< err.what() << std::endl;
11441154
series.iterations.container().erase(index);
1145-
return false;
1155+
return {err};
11461156
}
11471157
i.get().m_closed = internal::CloseStatus::Open;
11481158
}
@@ -1151,7 +1161,7 @@ void Series::readGorVBased(bool do_init)
11511161
i.get().m_closed = internal::CloseStatus::ParseAccessDeferred;
11521162
}
11531163
}
1154-
return true;
1164+
return {};
11551165
};
11561166

11571167
switch (iterationEncoding())
@@ -1173,11 +1183,15 @@ void Series::readGorVBased(bool do_init)
11731183
{
11741184
index = series.iterations.getAttribute("snapshot").get<uint64_t>();
11751185
}
1176-
if (!readSingleIteration(index, "", false, true))
1186+
if (auto err = readSingleIteration(index, "", false, true); err)
11771187
{
1178-
throw error::ParseError(
1179-
"In variable-based iteration encoding, read errors in the "
1180-
"first iteration are not recoverable (see warnings above).");
1188+
/*
1189+
* Cannot recover from errors in this place.
1190+
* If there is an error in the first iteration, the Series cannot
1191+
* be read in variable-based encoding.
1192+
* The read API will try to skip other iterations that have errors.
1193+
*/
1194+
throw *err;
11811195
}
11821196
break;
11831197
}

test/SerialIOTest.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5493,11 +5493,12 @@ void unfinished_iteration_test(
54935493
{
54945494
Series write(file, Access::CREATE, config);
54955495
auto it0 = write.writeIterations()[0];
5496+
auto it5 = write.writeIterations()[5];
54965497
/*
54975498
* With enabled invasive tests, this attribute will let the Iteration
54985499
* fail parsing.
54995500
*/
5500-
it0.setAttribute("__openPMD_internal_fail", "asking for trouble");
5501+
it5.setAttribute("__openPMD_internal_fail", "asking for trouble");
55015502
auto it10 = write.writeIterations()[10];
55025503
auto E_x = it10.meshes["E"]["x"];
55035504
auto e_density = it10.meshes["e_density"][RecordComponent::SCALAR];
@@ -5507,6 +5508,13 @@ void unfinished_iteration_test(
55075508
}
55085509
{
55095510
Series read(file, Access::READ_ONLY);
5511+
std::cout << "Going to list iterations in " << file << ":" << std::endl;
5512+
for (auto const &iteration : read.readIterations())
5513+
{
5514+
// @todo ensure that only the correct iterations are seen.
5515+
std::cout << "Seeing iteration " << iteration.iterationIndex
5516+
<< std::endl;
5517+
}
55105518
}
55115519
}
55125520

0 commit comments

Comments
 (0)