Skip to content

Commit f91c29b

Browse files
Bug fix: Don't forget closing files (#1083)
* Failing test * Bug fix: Don't forget closing files
1 parent dd0abbc commit f91c29b

2 files changed

Lines changed: 76 additions & 48 deletions

File tree

src/Series.cpp

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -547,18 +547,18 @@ SeriesInterface::flushFileBased( iterations_iterator begin, iterations_iterator
547547
if( IOHandler()->m_frontendAccess == Access::READ_ONLY )
548548
for( auto it = begin; it != end; ++it )
549549
{
550+
// Phase 1
550551
switch( openIterationIfDirty( it->first, it->second ) )
551552
{
552553
using IO = IterationOpened;
553-
case IO::RemainsClosed:
554-
continue;
555554
case IO::HasBeenOpened:
556-
// continue below
555+
it->second.flush();
556+
break;
557+
case IO::RemainsClosed:
557558
break;
558559
}
559560

560-
it->second.flush();
561-
561+
// Phase 2
562562
if( *it->second.m_closed ==
563563
Iteration::CloseStatus::ClosedInFrontend )
564564
{
@@ -567,38 +567,42 @@ SeriesInterface::flushFileBased( iterations_iterator begin, iterations_iterator
567567
IOTask( &it->second, std::move( fClose ) ) );
568568
*it->second.m_closed = Iteration::CloseStatus::ClosedInBackend;
569569
}
570+
571+
// Phase 3
570572
IOHandler()->flush();
571573
}
572574
else
573575
{
574576
bool allDirty = dirty();
575577
for( auto it = begin; it != end; ++it )
576578
{
579+
// Phase 1
577580
switch( openIterationIfDirty( it->first, it->second ) )
578581
{
579582
using IO = IterationOpened;
580-
case IO::RemainsClosed:
581-
continue;
582-
case IO::HasBeenOpened:
583-
// continue below
584-
break;
585-
}
586-
587-
/* as there is only one series,
588-
* emulate the file belonging to each iteration as not yet written
589-
*/
590-
written() = false;
591-
series.iterations.written() = false;
583+
case IO::HasBeenOpened: {
584+
/* as there is only one series,
585+
* emulate the file belonging to each iteration as not yet
586+
* written
587+
*/
588+
written() = false;
589+
series.iterations.written() = false;
592590

593-
dirty() |= it->second.dirty();
594-
std::string filename = iterationFilename( it->first );
595-
it->second.flushFileBased( filename, it->first );
591+
dirty() |= it->second.dirty();
592+
std::string filename = iterationFilename( it->first );
593+
it->second.flushFileBased( filename, it->first );
596594

597-
series.iterations.flush(
598-
auxiliary::replace_first( basePath(), "%T/", "" ) );
595+
series.iterations.flush(
596+
auxiliary::replace_first( basePath(), "%T/", "" ) );
599597

600-
flushAttributes();
598+
flushAttributes();
599+
break;
600+
}
601+
case IO::RemainsClosed:
602+
break;
603+
}
601604

605+
// Phase 2
602606
if( *it->second.m_closed ==
603607
Iteration::CloseStatus::ClosedInFrontend )
604608
{
@@ -608,6 +612,7 @@ SeriesInterface::flushFileBased( iterations_iterator begin, iterations_iterator
608612
*it->second.m_closed = Iteration::CloseStatus::ClosedInBackend;
609613
}
610614

615+
// Phase 3
611616
IOHandler()->flush();
612617

613618
/* reset the dirty bit for every iteration (i.e. file)
@@ -625,23 +630,26 @@ SeriesInterface::flushGorVBased( iterations_iterator begin, iterations_iterator
625630
if( IOHandler()->m_frontendAccess == Access::READ_ONLY )
626631
for( auto it = begin; it != end; ++it )
627632
{
633+
// Phase 1
628634
switch( openIterationIfDirty( it->first, it->second ) )
629635
{
630636
using IO = IterationOpened;
631-
case IO::RemainsClosed:
632-
continue;
633637
case IO::HasBeenOpened:
634-
// continue below
638+
it->second.flush();
639+
break;
640+
case IO::RemainsClosed:
635641
break;
636642
}
637643

638-
it->second.flush();
644+
// Phase 2
639645
if( *it->second.m_closed ==
640646
Iteration::CloseStatus::ClosedInFrontend )
641647
{
642648
// the iteration has no dedicated file in group-based mode
643649
*it->second.m_closed = Iteration::CloseStatus::ClosedInBackend;
644650
}
651+
652+
// Phase 3
645653
IOHandler()->flush();
646654
}
647655
else
@@ -654,26 +662,23 @@ SeriesInterface::flushGorVBased( iterations_iterator begin, iterations_iterator
654662
IOHandler()->enqueue(IOTask(this, fCreate));
655663
}
656664

657-
series.iterations.flush(auxiliary::replace_first(basePath(), "%T/", ""));
665+
series.iterations.flush(
666+
auxiliary::replace_first( basePath(), "%T/", "" ) );
658667

659668
for( auto it = begin; it != end; ++it )
660669
{
670+
// Phase 1
661671
switch( openIterationIfDirty( it->first, it->second ) )
662672
{
663673
using IO = IterationOpened;
664-
case IO::RemainsClosed:
665-
continue;
666674
case IO::HasBeenOpened:
667-
// continue below
668-
break;
669-
}
670-
if( !it->second.written() )
671-
{
672-
it->second.parent() = getWritable( &series.iterations );
673-
}
674-
switch( iterationEncoding() )
675-
{
676-
using IE = IterationEncoding;
675+
if( !it->second.written() )
676+
{
677+
it->second.parent() = getWritable( &series.iterations );
678+
}
679+
switch( iterationEncoding() )
680+
{
681+
using IE = IterationEncoding;
677682
case IE::groupBased:
678683
it->second.flushGroupBased( it->first );
679684
break;
@@ -683,8 +688,15 @@ SeriesInterface::flushGorVBased( iterations_iterator begin, iterations_iterator
683688
default:
684689
throw std::runtime_error(
685690
"[Series] Internal control flow error" );
691+
}
692+
break;
693+
case IO::RemainsClosed:
694+
break;
686695
}
687-
if( *it->second.m_closed == Iteration::CloseStatus::ClosedInFrontend )
696+
697+
// Phase 2
698+
if( *it->second.m_closed ==
699+
Iteration::CloseStatus::ClosedInFrontend )
688700
{
689701
// the iteration has no dedicated file in group-based mode
690702
*it->second.m_closed = Iteration::CloseStatus::ClosedInBackend;

test/SerialIOTest.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,17 @@ TEST_CASE( "adios2_char_portability", "[serial][adios2]" )
171171
}
172172
#endif
173173

174-
void
175-
write_and_read_many_iterations( std::string const & ext ) {
174+
void write_and_read_many_iterations(
175+
std::string const & ext, bool intermittentFlushes )
176+
{
176177
// the idea here is to trigger the maximum allowed number of file handles,
177178
// e.g., the upper limit in "ulimit -n" (default: often 1024). Once this
178179
// is reached, files should be closed automatically for open iterations
180+
181+
// By flushing the series before closing an iteration, we ensure that the
182+
// iteration is not dirty before closing
183+
// Our flushing logic must not forget to close even if the iteration is
184+
// otherwise untouched and needs not be flushed.
179185
unsigned int nIterations = auxiliary::getEnvNum( "OPENPMD_TEST_NFILES_MAX", 1030 );
180186
std::string filename = "../samples/many_iterations/many_iterations_%T." + ext;
181187

@@ -189,8 +195,12 @@ write_and_read_many_iterations( std::string const & ext ) {
189195
// std::cout << "Putting iteration " << i << std::endl;
190196
Iteration it = write.iterations[i];
191197
auto E_x = it.meshes["E"]["x"];
192-
E_x.resetDataset(ds);
193-
E_x.storeChunk(data, {0}, {10});
198+
E_x.resetDataset( ds );
199+
E_x.storeChunk( data, { 0 }, { 10 } );
200+
if( intermittentFlushes )
201+
{
202+
write.flush();
203+
}
194204
it.close();
195205
}
196206
// ~Series intentionally not yet called
@@ -201,8 +211,12 @@ write_and_read_many_iterations( std::string const & ext ) {
201211
iteration.second.open();
202212
// std::cout << "Reading iteration " << iteration.first <<
203213
// std::endl;
204-
auto E_x = iteration.second.meshes["E"]["x"];
205-
auto chunk = E_x.loadChunk<float>({0}, {10});
214+
auto E_x = iteration.second.meshes[ "E" ][ "x" ];
215+
auto chunk = E_x.loadChunk< float >( { 0 }, { 10 } );
216+
if( intermittentFlushes )
217+
{
218+
read.flush();
219+
}
206220
iteration.second.close();
207221

208222
auto array = chunk.get();
@@ -218,11 +232,13 @@ write_and_read_many_iterations( std::string const & ext ) {
218232

219233
TEST_CASE( "write_and_read_many_iterations", "[serial]" )
220234
{
235+
bool intermittentFlushes = false;
221236
if( auxiliary::directory_exists( "../samples/many_iterations" ) )
222237
auxiliary::remove_directory( "../samples/many_iterations" );
223238
for( auto const & t : testedFileExtensions() )
224239
{
225-
write_and_read_many_iterations( t );
240+
write_and_read_many_iterations( t, intermittentFlushes );
241+
intermittentFlushes = !intermittentFlushes;
226242
}
227243
}
228244

0 commit comments

Comments
 (0)