diff --git a/include/openPMD/IO/AbstractIOHandlerImplCommon.hpp b/include/openPMD/IO/AbstractIOHandlerImplCommon.hpp index 556fc81618..4a73259998 100644 --- a/include/openPMD/IO/AbstractIOHandlerImplCommon.hpp +++ b/include/openPMD/IO/AbstractIOHandlerImplCommon.hpp @@ -103,6 +103,8 @@ class AbstractIOHandlerImplCommon : public AbstractIOHandlerImpl FilePositionType * setAndGetFilePosition(Writable *writable, std::string extend); + void propagateFilestateToRoot(Writable *writable); + /* * The "virtual" methods here must be implemented by the child class, * but the references are resolved at compile time, hence not really @@ -138,8 +140,9 @@ AbstractIOHandlerImplCommon::makeFile( Writable *writable, std::string file, bool consider_open_files) { auto make_new = [&]() { - new (&writable->fileState) - internal::SharedFileState(std::in_place, file); + using SharedFileState = internal::SharedFileState; + writable->fileState.~SharedFileState(); + new (&writable->fileState) SharedFileState(std::in_place, file); m_files[std::move(file)].derive_from(writable->fileState); }; if (consider_open_files) @@ -311,4 +314,16 @@ auto AbstractIOHandlerImplCommon:: writable->abstractFilePosition = std::move(new_pos); return dynamic_cast(res); } + +template +void AbstractIOHandlerImplCommon:: + propagateFilestateToRoot(Writable *const writable) +{ + auto ancestor = writable; + while (ancestor->parent) + { + ancestor = ancestor->parent; + ancestor->fileState.derive_from(writable->fileState); + } +} } // namespace openPMD diff --git a/include/openPMD/IO/IOTask.hpp b/include/openPMD/IO/IOTask.hpp index 731372f9e1..a245b76729 100644 --- a/include/openPMD/IO/IOTask.hpp +++ b/include/openPMD/IO/IOTask.hpp @@ -141,6 +141,7 @@ struct OPENPMDAPI_EXPORT Parameter new Parameter(std::move(*this))); } + Writable *storageLocation = nullptr; std::string name = ""; }; @@ -187,6 +188,7 @@ struct OPENPMDAPI_EXPORT Parameter new Parameter(std::move(*this))); } + Writable *storageLocation = nullptr; std::string name = ""; using ParsePreference = internal::ParsePreference; std::shared_ptr out_parsePreference = diff --git a/include/openPMD/Series.hpp b/include/openPMD/Series.hpp index dbad461dc1..ab20c999ed 100644 --- a/include/openPMD/Series.hpp +++ b/include/openPMD/Series.hpp @@ -817,7 +817,7 @@ OPENPMD_private void flushParticlesPath(); void flushRankTable(); void readFileBased(); - void readOneIterationFileBased(std::string const &filePath); + void readOneIterationFileBased(std::string const &filePath, Iteration &it); /** * Note on re-parsing of a Series: * If init == false, the parsing process will seek for new diff --git a/src/IO/ADIOS/ADIOS2IOHandler.cpp b/src/IO/ADIOS/ADIOS2IOHandler.cpp index 156b2b0505..b2dc6b4b19 100644 --- a/src/IO/ADIOS/ADIOS2IOHandler.cpp +++ b/src/IO/ADIOS/ADIOS2IOHandler.cpp @@ -645,8 +645,11 @@ void ADIOS2IOHandlerImpl::createFile( { std::string name = parameters.name + fileSuffix(); + auto storageLocation = + parameters.storageLocation ? parameters.storageLocation : writable; auto &file = - makeFile(writable, name, /* consider_open_files = */ false); + makeFile(storageLocation, name, /* consider_open_files = */ false); + propagateFilestateToRoot(storageLocation); auto &file_state = **file; if (m_handler->m_backendAccess != Access::CREATE && m_handler->m_backendAccess != Access::APPEND && @@ -945,9 +948,11 @@ void ADIOS2IOHandlerImpl::openFile( std::string name = parameters.name + fileSuffix(); - auto &file = makeFile(writable, name, /* consider_open_files = */ true); - - associateWithFile(writable, file); + auto storageLocation = + parameters.storageLocation ? parameters.storageLocation : writable; + auto &file = + makeFile(storageLocation, name, /* consider_open_files = */ true); + propagateFilestateToRoot(storageLocation); writable->written = true; writable->abstractFilePosition = std::make_shared(); diff --git a/src/IO/AbstractIOHandlerImpl.cpp b/src/IO/AbstractIOHandlerImpl.cpp index 7675cc3e07..ec61899b75 100644 --- a/src/IO/AbstractIOHandlerImpl.cpp +++ b/src/IO/AbstractIOHandlerImpl.cpp @@ -125,7 +125,19 @@ std::future AbstractIOHandlerImpl::flush() "->", i.writable, "] CREATE_FILE: ", - parameter.name); + parameter.name, + [ptr = parameter.storageLocation]() { + if (ptr) + { + std::stringstream s; + s << " into " << ptr; + return s.str(); + } + else + { + return std::string(); + } + }); createFile(i.writable, parameter); break; } @@ -193,7 +205,19 @@ std::future AbstractIOHandlerImpl::flush() "->", i.writable, "] OPEN_FILE: ", - parameter.name); + parameter.name, + [ptr = parameter.storageLocation]() { + if (ptr) + { + std::stringstream s; + s << " into " << ptr; + return s.str(); + } + else + { + return std::string(); + } + }); openFile(i.writable, parameter); break; } diff --git a/src/IO/JSON/JSONIOHandlerImpl.cpp b/src/IO/JSON/JSONIOHandlerImpl.cpp index c842368a51..122fa6ead8 100644 --- a/src/IO/JSON/JSONIOHandlerImpl.cpp +++ b/src/IO/JSON/JSONIOHandlerImpl.cpp @@ -501,8 +501,11 @@ void JSONIOHandlerImpl::createFile( { std::string name = parameters.name + m_originalExtension; + auto storageLocation = + parameters.storageLocation ? parameters.storageLocation : writable; auto &file = - makeFile(writable, name, /* consider_open_files = */ false); + makeFile(storageLocation, name, /* consider_open_files = */ false); + propagateFilestateToRoot(storageLocation); auto &file_state = **file; auto file_exists = auxiliary::file_exists(fullPath(file_state)); @@ -984,7 +987,11 @@ void JSONIOHandlerImpl::openFile( std::string name = parameter.name + m_originalExtension; - auto &file = makeFile(writable, name, /* consider_open_files = */ true); + auto storageLocation = + parameter.storageLocation ? parameter.storageLocation : writable; + auto &file = + makeFile(storageLocation, name, /* consider_open_files = */ true); + propagateFilestateToRoot(storageLocation); associateWithFile(writable, file); diff --git a/src/Iteration.cpp b/src/Iteration.cpp index 28839fea3b..0bf8059c36 100644 --- a/src/Iteration.cpp +++ b/src/Iteration.cpp @@ -208,6 +208,7 @@ void Iteration::flushFileBased( /* create file */ Parameter fCreate; fCreate.name = filename; + fCreate.storageLocation = &this->writable(); IOHandler()->enqueue(IOTask(&s.writable(), fCreate)); /* @@ -403,7 +404,7 @@ void Iteration::readFileBased( } auto series = retrieveSeries(); - series.readOneIterationFileBased(filePath); + series.readOneIterationFileBased(filePath, *this); get().m_overrideFilebasedFilename = filePath; read_impl(groupPath); diff --git a/src/Series.cpp b/src/Series.cpp index 735d88ac66..b0ab59bd12 100644 --- a/src/Series.cpp +++ b/src/Series.cpp @@ -1565,7 +1565,6 @@ void Series::flushParticlesPath() void Series::readFileBased() { auto &series = get(); - Parameter fOpen; Parameter aRead; // Tell the backend that we are parsing file-based iteration encoding. @@ -1757,7 +1756,8 @@ void Series::readFileBased() "Please specify '%0T' or open as read-only."); } -void Series::readOneIterationFileBased(std::string const &filePath) +void Series::readOneIterationFileBased( + std::string const &filePath, Iteration &it) { auto &series = get(); @@ -1765,6 +1765,7 @@ void Series::readOneIterationFileBased(std::string const &filePath) Parameter aRead; fOpen.name = filePath; + fOpen.storageLocation = &it.writable(); IOHandler()->enqueue(IOTask(this, fOpen)); IOHandler()->flush(internal::defaultFlushParams); series.iterations.parent() = getWritable(this); @@ -2683,6 +2684,7 @@ void Series::openIteration(IterationIndex_t index, Iteration iteration) // open the iteration's file again Parameter fOpen; fOpen.name = iterationFilename(index); + fOpen.storageLocation = &iteration.writable(); IOHandler()->enqueue(IOTask(this, fOpen)); /* open base path */