Skip to content

Commit

Permalink
Apply redesign to Iteration class
Browse files Browse the repository at this point in the history
  • Loading branch information
franzpoeschel committed Oct 1, 2021
1 parent 950bc0c commit 3236c0e
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 127 deletions.
155 changes: 86 additions & 69 deletions include/openPMD/Iteration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,78 @@

namespace openPMD
{
namespace internal
{
/**
* @brief Whether an iteration has been closed yet.
*
*/
enum class CloseStatus
{
ParseAccessDeferred, //!< The reader has not yet parsed this iteration
Open, //!< Iteration has not been closed
ClosedInFrontend, /*!< Iteration has been closed, but task has not yet
been propagated to the backend */
ClosedInBackend, /*!< Iteration has been closed and task has been
propagated to the backend */
ClosedTemporarily /*!< Iteration has been closed internally and may
be reopened later */
};

struct DeferredParseAccess
{
/**
* The group path within /data containing this iteration.
* Example: "1" for iteration 1, "" in variable-based iteration
* encoding.
*/
std::string path;
/**
* The iteration index as accessed by the user in series.iterations[i]
*/
uint64_t iteration = 0;
/**
* If this iteration is part of a Series with file-based layout.
* (Group- and variable-based parsing shares the same code logic.)
*/
bool fileBased = false;
/**
* If fileBased == true, the file name (without file path) of the file
* containing this iteration.
*/
std::string filename;
};

class IterationData : public AttributableData
{
public:
/*
* An iteration may be logically closed in the frontend,
* but not necessarily yet in the backend.
* Will be propagated to the backend upon next flush.
* Store the current status.
* Once an iteration has been closed, no further flushes shall be performed.
* If flushing a closed file, the old file may otherwise be overwritten.
*/
CloseStatus m_closed = CloseStatus::Open;

/**
* Whether a step is currently active for this iteration.
* Used for file-based iteration layout, see Series.hpp for
* group-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.
*/
StepStatus m_stepStatus = StepStatus::NoStep;

auxiliary::Option< DeferredParseAccess > m_deferredParseAccess{};
};
}
/** @brief Logical compilation of data from one snapshot (e.g. a single simulation cycle).
*
* @see https://github.com/openPMD/openPMD-standard/blob/latest/STANDARD.md#required-attributes-for-the-basepath
*/
class Iteration : public LegacyAttributable
class Iteration : public Attributable
{
template<
typename T,
Expand Down Expand Up @@ -150,42 +217,32 @@ class Iteration : public LegacyAttributable
bool
closedByWriter() const;

Container< Mesh > meshes;
Container< ParticleSpecies > particles; //particleSpecies?
Container< Mesh > meshes{};
Container< ParticleSpecies > particles{}; //particleSpecies?

virtual ~Iteration() = default;
private:
Iteration();

struct DeferredParseAccess
std::shared_ptr< internal::IterationData > m_iterationData{
new internal::IterationData };

inline internal::IterationData const & get() const
{
/**
* The group path within /data containing this iteration.
* Example: "1" for iteration 1, "" in variable-based iteration
* encoding.
*/
std::string path;
/**
* The iteration index as accessed by the user in series.iterations[i]
*/
uint64_t iteration = 0;
/**
* If this iteration is part of a Series with file-based layout.
* (Group- and variable-based parsing shares the same code logic.)
*/
bool fileBased = false;
/**
* If fileBased == true, the file name (without file path) of the file
* containing this iteration.
*/
std::string filename;
};
return *m_iterationData;
}

inline internal::IterationData & get()
{
return const_cast< internal::IterationData & >(
static_cast< Iteration const * >( this )->get() );
}

void flushFileBased(std::string const&, uint64_t);
void flushGroupBased(uint64_t);
void flushVariableBased(uint64_t);
void flush();
void deferParseAccess( DeferredParseAccess );
void deferParseAccess( internal::DeferredParseAccess );
/*
* Control flow for read(), readFileBased(), readGroupBased() and
* read_impl():
Expand All @@ -198,7 +255,7 @@ class Iteration : public LegacyAttributable
* allow for those different control flows.
* Finally, read_impl() is called which contains the common parsing
* logic for an iteration.
*
*
* reread() reads again an Iteration that has been previously read.
* Calling it on an Iteration not yet parsed is an error.
*
Expand All @@ -209,47 +266,7 @@ class Iteration : public LegacyAttributable
void readGorVBased( std::string const & groupPath );
void read_impl( std::string const & groupPath );

/**
* @brief Whether an iteration has been closed yet.
*
*/
enum class CloseStatus
{
ParseAccessDeferred, //!< The reader has not yet parsed this iteration
Open, //!< Iteration has not been closed
ClosedInFrontend, /*!< Iteration has been closed, but task has not yet
been propagated to the backend */
ClosedInBackend, /*!< Iteration has been closed and task has been
propagated to the backend */
ClosedTemporarily /*!< Iteration has been closed internally and may
be reopened later */
};

/*
* An iteration may be logically closed in the frontend,
* but not necessarily yet in the backend.
* Will be propagated to the backend upon next flush.
* Store the current status.
* Once an iteration has been closed, no further flushes shall be performed.
* If flushing a closed file, the old file may otherwise be overwritten.
*/
std::shared_ptr< CloseStatus > m_closed =
std::make_shared< CloseStatus >( CloseStatus::Open );

/**
* Whether a step is currently active for this iteration.
* Used for file-based iteration layout, see Series.hpp for
* group-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.
*/
std::shared_ptr< StepStatus > m_stepStatus =
std::make_shared< StepStatus >( StepStatus::NoStep );

std::shared_ptr< auxiliary::Option< DeferredParseAccess > >
m_deferredParseAccess =
std::make_shared< auxiliary::Option< DeferredParseAccess > >(
auxiliary::Option< DeferredParseAccess >() );

/**
* @brief Begin an IO step on the IO file (or file-like object)
Expand Down Expand Up @@ -305,15 +322,15 @@ class Iteration : public LegacyAttributable

/**
* @brief Link with parent.
*
*
* @param w The Writable representing the parent.
*/
virtual void linkHierarchy(Writable& w);

/**
* @brief Access an iteration in read mode that has potentially not been
* parsed yet.
*
*
*/
void runDeferredParseAccess();
}; // Iteration
Expand Down
39 changes: 22 additions & 17 deletions src/Iteration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@

namespace openPMD
{
Iteration::Iteration()
: meshes{Container< Mesh >()},
particles{Container< ParticleSpecies >()}
using internal::CloseStatus;
using internal::DeferredParseAccess;

Iteration::Iteration() : Attributable{ nullptr }
{
Attributable::setData( m_iterationData );
setTime(static_cast< double >(0));
setDt(static_cast< double >(1));
setTimeUnitSI(1);
Expand Down Expand Up @@ -83,29 +85,30 @@ Iteration &
Iteration::close( bool _flush )
{
using bool_type = unsigned char;
auto & it = get();
if( this->IOHandler()->m_frontendAccess != Access::READ_ONLY )
{
setAttribute< bool_type >( "closed", 1u );
}
StepStatus flag = getStepStatus();
// update close status
switch( *m_closed )
switch( it.m_closed )
{
case CloseStatus::Open:
case CloseStatus::ClosedInFrontend:
*m_closed = CloseStatus::ClosedInFrontend;
it.m_closed = CloseStatus::ClosedInFrontend;
break;
case CloseStatus::ClosedTemporarily:
// should we bother to reopen?
if( dirtyRecursive() )
{
// let's reopen
*m_closed = CloseStatus::ClosedInFrontend;
it.m_closed = CloseStatus::ClosedInFrontend;
}
else
{
// don't reopen
*m_closed = CloseStatus::ClosedInBackend;
it.m_closed = CloseStatus::ClosedInBackend;
}
break;
case CloseStatus::ParseAccessDeferred:
Expand Down Expand Up @@ -148,9 +151,10 @@ Iteration::close( bool _flush )
Iteration &
Iteration::open()
{
if( *m_closed == CloseStatus::ParseAccessDeferred )
auto & it = get();
if( it.m_closed == CloseStatus::ParseAccessDeferred )
{
*m_closed = CloseStatus::Open;
it.m_closed = CloseStatus::Open;
}
runDeferredParseAccess();
Series s = retrieveSeries();
Expand All @@ -164,7 +168,7 @@ Iteration::open()
bool
Iteration::closed() const
{
switch( *m_closed )
switch( get().m_closed )
{
case CloseStatus::ParseAccessDeferred:
case CloseStatus::Open:
Expand Down Expand Up @@ -323,17 +327,18 @@ Iteration::flush()

void Iteration::deferParseAccess( DeferredParseAccess dr )
{
*m_deferredParseAccess =
get().m_deferredParseAccess =
auxiliary::makeOption< DeferredParseAccess >( std::move( dr ) );
}

void Iteration::read()
{
if( !m_deferredParseAccess->has_value() )
auto & it = get();
if( !it.m_deferredParseAccess.has_value() )
{
return;
}
auto const & deferred = m_deferredParseAccess->get();
auto const & deferred = it.m_deferredParseAccess.get();
if( deferred.fileBased )
{
readFileBased( deferred.filename, deferred.path );
Expand All @@ -343,12 +348,12 @@ void Iteration::read()
readGorVBased( deferred.path );
}
// reset this thing
*m_deferredParseAccess = auxiliary::Option< DeferredParseAccess >();
it.m_deferredParseAccess = auxiliary::Option< DeferredParseAccess >();
}

void Iteration::reread( std::string const & path )
{
if( m_deferredParseAccess->has_value() )
if( get().m_deferredParseAccess.has_value() )
{
throw std::runtime_error(
"[Iteration] Internal control flow error: Trying to reread an "
Expand Down Expand Up @@ -614,7 +619,7 @@ Iteration::getStepStatus()
{
using IE = IterationEncoding;
case IE::fileBased:
return *this->m_stepStatus;
return get().m_stepStatus;
case IE::groupBased:
case IE::variableBased:
return s.get().m_stepStatus;
Expand All @@ -631,7 +636,7 @@ Iteration::setStepStatus( StepStatus status )
{
using IE = IterationEncoding;
case IE::fileBased:
*this->m_stepStatus = status;
get().m_stepStatus = status;
break;
case IE::groupBased:
case IE::variableBased:
Expand Down
6 changes: 3 additions & 3 deletions src/ReadIterations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ SeriesIterator::SeriesIterator( Series series )
* Use case: See Python ApiTest testListSeries:
* Call listSeries twice.
*/
if( *it->second.m_closed !=
Iteration::CloseStatus::ClosedInBackend )
if( it->second.get().m_closed !=
internal::CloseStatus::ClosedInBackend )
{
it->second.open();
}
Expand Down Expand Up @@ -136,7 +136,7 @@ SeriesIterator & SeriesIterator::operator++()
return *this;
}
m_currentIteration = it->first;
if( *it->second.m_closed != Iteration::CloseStatus::ClosedInBackend )
if( it->second.get().m_closed != internal::CloseStatus::ClosedInBackend )
{
it->second.open();
}
Expand Down
Loading

0 comments on commit 3236c0e

Please sign in to comment.