2424#include " openPMD/Error.hpp"
2525#include " openPMD/IO/AbstractIOHandler.hpp"
2626#include " openPMD/IO/AbstractIOHandlerImpl.hpp"
27+ #include " openPMD/IO/Access.hpp"
2728#include " openPMD/ThrowError.hpp"
2829#include " openPMD/auxiliary/Filesystem.hpp"
2930#include " openPMD/auxiliary/JSONMatcher.hpp"
@@ -349,8 +350,8 @@ namespace
349350
350351 auto get_mandatory = [&](char const *key,
351352 bool lowercase) -> std::string {
352- auto const &val = * optionalOrElse (
353- get_key (" mode " ), [&]() -> nlohmann::json const * {
353+ auto const &val =
354+ * optionalOrElse ( get_key (key ), [&]() -> nlohmann::json const * {
354355 throw error::BackendConfigSchema (
355356 {configLocation, " mode" , key}, " Mandatory key." );
356357 });
@@ -394,7 +395,7 @@ namespace
394395 }
395396 static_cast <decltype (then)>(then)(val.get <bool >());
396397 };
397- auto modeString = get_mandatory (" type " , true );
398+ auto modeString = get_mandatory (" provider " , true );
398399
399400 if (modeString == " stdio" )
400401 {
@@ -465,8 +466,8 @@ namespace
465466 }
466467} // namespace
467468
468- auto JSONIOHandlerImpl::retrieveDatasetMode (
469- openPMD::json::TracingJSON &config) const -> DatasetMode_s
469+ auto JSONIOHandlerImpl::retrieveDatasetMode (openPMD::json::TracingJSON &config)
470+ -> DatasetMode_s
470471{
471472 // start with / copy from current config
472473 auto res = m_datasetMode;
@@ -484,8 +485,20 @@ auto JSONIOHandlerImpl::retrieveDatasetMode(
484485 auto mode = datasetConfig[" mode" ];
485486 if (mode.json ().is_object ())
486487 {
487- parse_external_mode (
488- std::move (mode), std::nullopt , configLocation, res);
488+ if (access::writeOnly (m_handler->m_backendAccess ))
489+ {
490+ parse_external_mode (
491+ std::move (mode), std::nullopt , configLocation, res);
492+ }
493+ else
494+ {
495+ // sic! initialize the deferred json config as a new
496+ // tracing object
497+ m_deferredExternalBlockstorageConfig =
498+ std::make_optional<openPMD::json::TracingJSON>(
499+ config.json (), config.originallySpecifiedAs );
500+ config.declareFullyRead ();
501+ }
489502 }
490503 else
491504 {
@@ -661,6 +674,14 @@ void JSONIOHandlerImpl::createFile(
661674 access::write (m_handler->m_backendAccess ),
662675 " [JSON] Creating a file in read-only mode is not possible." );
663676
677+ if (m_deferredExternalBlockstorageConfig.has_value ())
678+ {
679+ throw error::Internal (
680+ " Creation of external block storage backend was deferred until "
681+ " opening the first file, but a file is created before any was "
682+ " opened." );
683+ }
684+
664685 /*
665686 * Need to resolve this later than init() since the openPMD version might be
666687 * specified after the creation of the IOHandler.
@@ -1104,6 +1125,28 @@ void JSONIOHandlerImpl::openFile(
11041125
11051126 auto file = std::get<0 >(getPossiblyExisting (name));
11061127
1128+ if (m_deferredExternalBlockstorageConfig.has_value ())
1129+ {
1130+ auto const &contents = obtainJsonContents (file);
1131+ auto previousConfig = [&]() -> std::optional<nlohmann::json const *> {
1132+ if (contents->contains (" external_storage" ))
1133+ {
1134+ return std::make_optional<nlohmann::json const *>(
1135+ &contents->at (" external_storage" ));
1136+ }
1137+ else
1138+ {
1139+ return std::nullopt ;
1140+ }
1141+ }();
1142+ parse_external_mode (
1143+ std::move (*m_deferredExternalBlockstorageConfig),
1144+ previousConfig,
1145+ backendConfigKey (),
1146+ m_datasetMode);
1147+ m_attributeMode.m_specificationVia = SpecificationVia::Manually;
1148+ }
1149+
11071150 associateWithFile (writable, file);
11081151
11091152 writable->written = true ;
@@ -2242,6 +2285,9 @@ JSONIOHandlerImpl::obtainJsonContents(File const &file)
22422285 auto res = serialImplementation ();
22432286#endif
22442287
2288+ bool initialize_external_block_storage =
2289+ m_deferredExternalBlockstorageConfig.has_value ();
2290+
22452291 if (res->contains (JSONDefaults::openpmd_internal))
22462292 {
22472293 auto const &openpmd_internal = res->at (JSONDefaults::openpmd_internal);
@@ -2272,6 +2318,10 @@ JSONIOHandlerImpl::obtainJsonContents(File const &file)
22722318 {
22732319 m_datasetMode.m_mode = DatasetMode::Template;
22742320 }
2321+ else if (modeOption.value () == " external" )
2322+ {
2323+ initialize_external_block_storage = true ;
2324+ }
22752325 else
22762326 {
22772327 std::cerr << " [JSON/TOML backend] Warning: Invalid value '"
@@ -2315,6 +2365,31 @@ JSONIOHandlerImpl::obtainJsonContents(File const &file)
23152365 }
23162366 }
23172367 }
2368+
2369+ if (initialize_external_block_storage)
2370+ {
2371+ auto previousConfig = [&]() -> std::optional<nlohmann::json const *> {
2372+ if (res->contains (" external_storage" ))
2373+ {
2374+ return std::make_optional<nlohmann::json const *>(
2375+ &res->at (" external_storage" ));
2376+ }
2377+ else
2378+ {
2379+ return std::nullopt ;
2380+ }
2381+ }();
2382+ parse_external_mode (
2383+ m_deferredExternalBlockstorageConfig.has_value ()
2384+ ? std::move (*m_deferredExternalBlockstorageConfig)
2385+ : openPMD::json::TracingJSON (),
2386+ previousConfig,
2387+ backendConfigKey (),
2388+ m_datasetMode);
2389+ m_attributeMode.m_specificationVia = SpecificationVia::Manually;
2390+ m_deferredExternalBlockstorageConfig.reset ();
2391+ }
2392+
23182393 m_jsonVals.emplace (file, res);
23192394 return res;
23202395}
0 commit comments