Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
VariableIOReaderMng.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* VariableIOMng.cc (C) 2000-2026 */
9/* */
10/* Class managing input/output for variables. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/internal/VariableMng.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ParallelFatalErrorException.h"
18#include "arcane/utils/IObservable.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/StringBuilder.h"
21#include "arcane/utils/MD5HashAlgorithm.h"
22#include "arcane/utils/SHA1HashAlgorithm.h"
23#include "arcane/utils/OStringStream.h"
24#include "arcane/utils/PlatformUtils.h"
25#include "arcane/utils/JSONReader.h"
26#include "arcane/utils/ValueConvert.h"
27
28#include "arcane/core/IXmlDocumentHolder.h"
29#include "arcane/core/XmlNode.h"
30#include "arcane/core/VariableMetaData.h"
31#include "arcane/core/IData.h"
32#include "arcane/core/IMesh.h"
33#include "arcane/core/Properties.h"
34#include "arcane/core/Timer.h"
35#include "arcane/core/VarRefEnumerator.h"
36#include "arcane/core/CheckpointInfo.h"
37#include "arcane/core/Directory.h"
38#include "arcane/core/ISerializedData.h"
39#include "arcane/core/VariableBuildInfo.h"
40#include "arcane/core/XmlNodeList.h"
41#include "arcane/core/IMeshMng.h"
42#include "arcane/core/IMeshFactoryMng.h"
43#include "arcane/core/MeshBuildInfo.h"
44#include "arcane/core/internal/IDataInternal.h"
45
46#include "arcane/core/ICheckpointReader.h"
47#include "arcane/core/IDataReader.h"
48#include "arcane/core/IDataReader2.h"
49
50#include "arcane/core/ISubDomain.h"
51#include "arcane/core/IParallelMng.h"
52
53#include "arcane/core/internal/IParallelMngInternal.h"
54#include "arcane/core/internal/IVariableInternal.h"
55
56// TODO: handle 64-bit hash.
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61namespace Arcane
62{
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67// Extraction of type info from a character string
68// NOTE: The extraction must be consistent with the construction
69// in Variable.cc
71{
72 public:
73
74 explicit VariableDataTypeInfo(const String& full_type)
75 : m_is_partial(false)
76 {
77 std::vector<String> split_strs;
78 full_type.split(split_strs, '.');
79 size_t nb_split = split_strs.size();
80 if (nb_split == 5) {
81 if (split_strs[4] != "Partial")
82 ARCANE_FATAL("Invalid value for partial full_type '{0}'", full_type);
83 m_is_partial = true;
84 --nb_split;
85 }
86 if (nb_split != 4)
87 ARCANE_FATAL("Invalid value for full_type '{0}'", full_type);
88 m_data_type_name = split_strs[0];
89 m_item_kind_name = split_strs[1];
90 m_dimension = split_strs[2];
91 m_multi_tag = split_strs[3];
92 }
93
94 public:
95
96 const String& dataTypeName() const { return m_data_type_name; }
97 const String& itemKindName() const { return m_item_kind_name; }
98 const String& dimension() const { return m_dimension; }
99 const String& multiTag() const { return m_multi_tag; }
100 bool isPartial() const { return m_is_partial; }
101
102 private:
103
104 String m_data_type_name;
105 String m_item_kind_name;
106 String m_dimension;
107 String m_multi_tag;
108 bool m_is_partial;
109};
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
118{
119 public:
120
121 virtual ~IDataReaderWrapper() = default;
122
123 public:
124
125 virtual void beginRead(const VariableCollection& vars) = 0;
126 virtual void read(VariableMetaData* vmd, IVariable* var, IData* data) = 0;
127 virtual void endRead() = 0;
128};
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
137: public IDataReaderWrapper
138{
139 public:
140
141 explicit OldDataReaderWrapper(IDataReader* reader)
142 : m_reader(reader)
143 {}
144 void beginRead(const VariableCollection& vars) override
145 {
146 return m_reader->beginRead(vars);
147 }
148 void read(VariableMetaData* vmd, IVariable* var, IData* data) override
149 {
150 ARCANE_UNUSED(vmd);
151 m_reader->read(var, data);
152 }
153 void endRead() override
154 {
155 return m_reader->endRead();
156 }
157
158 private:
159
160 IDataReader* m_reader;
161};
162
163/*---------------------------------------------------------------------------*/
164/*---------------------------------------------------------------------------*/
165
170: public IDataReaderWrapper
171{
172 public:
173
174 explicit DataReaderWrapper(IDataReader2* reader)
175 : m_reader(reader)
176 {}
177 void beginRead(const VariableCollection& vars) override
178 {
179 ARCANE_UNUSED(vars);
180 return m_reader->beginRead(DataReaderInfo());
181 }
182 void read(VariableMetaData* vmd, IVariable* var, IData* data) override
183 {
184 ARCANE_UNUSED(var);
185 m_reader->read(VariableDataReadInfo(vmd, data));
186 }
187 void endRead() override
188 {
189 return m_reader->endRead();
190 }
191
192 private:
193
194 IDataReader2* m_reader;
195};
196
197/*---------------------------------------------------------------------------*/
198/*---------------------------------------------------------------------------*/
199
200class VariableMetaDataList
201{
202 public:
203
204 typedef std::map<String, Ref<VariableMetaData>> VMDMap;
205
206 public:
207
208 VariableMetaDataList() = default;
209 VariableMetaDataList(const VariableMetaDataList& rhs) = delete;
210 VariableMetaDataList& operator=(const VariableMetaDataList& rhs) = delete;
211 ~VariableMetaDataList()
212 {
213 clear();
214 }
215
216 public:
217
218 VariableMetaData* add(const String& base_name, const String& mesh_name,
219 const String& family_name, const String& group_name,
220 bool is_partial)
221 {
222 auto vmd = makeRef(new VariableMetaData(base_name, mesh_name, family_name, group_name, is_partial));
223 return add(vmd);
224 }
226 {
227 m_vmd_map.insert(std::make_pair(vmd->fullName(), vmd));
228 return vmd.get();
229 }
230 void clear()
231 {
232 m_vmd_map.clear();
233 }
234 VariableMetaData* findMetaData(const String& full_name)
235 {
236 auto x = m_vmd_map.find(full_name);
237 if (x != m_vmd_map.end())
238 return x->second.get();
239 return nullptr;
240 }
241 VMDMap::const_iterator begin() const { return m_vmd_map.begin(); }
242 VMDMap::const_iterator end() const { return m_vmd_map.end(); }
243 void setHashAlgorithmName(const String& v) { m_hash_algorithm = v; }
244 const String& hashAlgorithmName() const { return m_hash_algorithm; }
245
246 public:
247
248 std::map<String, Ref<VariableMetaData>> m_vmd_map;
249 String m_hash_algorithm;
250};
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
261class VariableReaderMng
262: public TraceAccessor
263{
264 struct VarReadInfo
265 {
266 public:
267
268 VarReadInfo(IVariable* var, IData* data, VariableMetaData* meta_data)
269 : m_variable(var)
270 , m_data(data)
271 , m_meta_data(meta_data)
272 {}
273
274 public:
275
276 IVariable* m_variable;
277 IData* m_data;
278 VariableMetaData* m_meta_data;
279 };
280
281 public:
282
283 explicit VariableReaderMng(ITraceMng* tm)
284 : TraceAccessor(tm)
285 {}
286
287 public:
288
289 void readVariablesData(IVariableMng* vm, VariableIOReaderMng::IDataReaderWrapper* reader);
290 VariableMetaDataList& variableMetaDataList() { return m_vmd_list; }
291 const VariableList& variablesToRead() { return m_vars_to_read; }
292
293 private:
294
295 VariableMetaDataList m_vmd_list;
296 VariableList m_vars_to_read;
297 UniqueArray<VarReadInfo> m_var_read_info_list;
298
299 private:
300
301 void _buildVariablesToRead(IVariableMng* vm);
302};
303
304/*---------------------------------------------------------------------------*/
305/*---------------------------------------------------------------------------*/
306
307void VariableReaderMng::
308_buildVariablesToRead(IVariableMng* vm)
309{
310 m_vars_to_read.clear();
311 m_var_read_info_list.clear();
312 for (const auto& x : m_vmd_list) {
313 const String& full_name = x.first;
314 IVariable* var = vm->findVariableFullyQualified(full_name);
315 if (!var)
316 ARCANE_FATAL("Var {0} not in VariableMng", full_name);
317 m_vars_to_read.add(var);
318 m_var_read_info_list.add(VarReadInfo(var, var->data(), x.second.get()));
319 }
320}
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
324
325void VariableReaderMng::
326readVariablesData(IVariableMng* vm, VariableIOReaderMng::IDataReaderWrapper* reader)
327{
328 _buildVariablesToRead(vm);
329 reader->beginRead(m_vars_to_read);
330 for (const auto& ivar : m_var_read_info_list) {
331 // NOTE: var may be null
332 IVariable* var = ivar.m_variable;
333 IData* data = ivar.m_data;
334 VariableMetaData* vmd = ivar.m_meta_data;
335 String exception_message;
336 bool has_error = false;
337 try {
338 reader->read(vmd, var, data);
339 if (var)
340 var->notifyEndRead();
341 }
342 catch (const Exception& ex) {
343 OStringStream ostr;
344 ostr() << ex;
345 exception_message = ostr.str();
346 has_error = true;
347 }
348 catch (const std::exception& ex) {
349 exception_message = ex.what();
350 has_error = true;
351 }
352 if (has_error) {
353 OStringStream ostr;
354 String var_full_name = vmd->fullName();
355 ostr() << "Variable = " << var_full_name;
356 if (var) {
357 for (VarRefEnumerator ivar(var); ivar.hasNext(); ++ivar) {
358 VariableRef* ref = *ivar;
359 String s = ref->assignmentStackTrace();
360 if (!s.null())
361 ostr() << "Stack assignment: " << s;
362 }
363 }
364
365 ARCANE_FATAL("Can not read variable variable={0} exception={1} infos={2}",
366 var_full_name, exception_message, ostr.str());
367 }
368 }
369 reader->endRead();
370}
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
374
375/*---------------------------------------------------------------------------*/
376/*---------------------------------------------------------------------------*/
377
378VariableIOReaderMng::
379VariableIOReaderMng(VariableMng* vm)
380: TraceAccessor(vm->traceMng())
381, m_variable_mng(vm)
382, m_is_use_json_metadata(true)
383{
384 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_JSON_METADATA", true))
385 m_is_use_json_metadata = (v.value() != 0);
386}
387
388/*---------------------------------------------------------------------------*/
389/*---------------------------------------------------------------------------*/
390
391/*---------------------------------------------------------------------------*/
392/*---------------------------------------------------------------------------*/
393
394void VariableIOReaderMng::
395readCheckpoint(ICheckpointReader* service)
396{
397 Trace::Setter mci(traceMng(), _msgClassName());
398
399 if (!service)
400 ARCANE_FATAL("No protection service specified");
401
402 service->notifyBeginRead();
403
404 IDataReader* data_reader = service->dataReader();
405 if (!data_reader)
406 ARCANE_FATAL("no dataReader()");
407 String meta_data = data_reader->metaData();
408
409 if (meta_data.null())
410 ARCANE_FATAL("No meta-data in checkpoint.");
411
412 OldDataReaderWrapper wrapper(data_reader);
413
414 info(6) << "METADATA (ICheckpointReader): FromCheckpoint: " << meta_data;
415
416 VariableReaderMng var_read_mng(traceMng());
417 VariableMetaDataList& vmd_list = var_read_mng.variableMetaDataList();
418 {
419 _readMetaData(vmd_list, meta_data.bytes());
420 _createVariablesFromMetaData(vmd_list);
421 _readVariablesData(var_read_mng, &wrapper);
422 }
423
424 service->notifyEndRead();
425 _checkHashFunction(vmd_list);
426}
427
428/*---------------------------------------------------------------------------*/
429/*---------------------------------------------------------------------------*/
430
431void VariableIOReaderMng::
432readCheckpoint(const CheckpointReadInfo& infos)
433{
434 Trace::Setter mci(traceMng(), _msgClassName());
435
436 ICheckpointReader2* service = infos.reader();
437 ARCANE_CHECK_POINTER2(service, "No checkpoint service specified");
438
439 IParallelMng* pm = infos.parallelMng();
440 ARCANE_CHECK_POINTER2(pm, "no parallelMng()");
441
442 service->notifyBeginRead(infos);
443
444 IDataReader2* data_reader = service->dataReader();
445 ARCANE_CHECK_POINTER2(data_reader, "No dataReader()");
446
447 UniqueArray<Byte> meta_data_bytes;
448 data_reader->fillMetaData(meta_data_bytes);
449 if (meta_data_bytes.empty())
450 ARCANE_FATAL("No meta-data in checkpoint.");
451
452 DataReaderWrapper wrapper(data_reader);
453
454 info(6) << "METADATA (ICheckpointReader2): FromCheckpoint: " << String(meta_data_bytes);
455
456 VariableReaderMng var_read_mng(traceMng());
457 VariableMetaDataList& vmd_list = var_read_mng.variableMetaDataList();
458 {
459 _readMetaData(vmd_list, meta_data_bytes);
460 _createVariablesFromMetaData(vmd_list);
461 _readVariablesData(var_read_mng, &wrapper);
462 }
463
464 service->notifyEndRead();
465 _checkHashFunction(vmd_list);
466}
467
468/*---------------------------------------------------------------------------*/
469/*---------------------------------------------------------------------------*/
470
471void VariableIOReaderMng::
472readVariables(IDataReader* reader, IVariableFilter* filter)
473{
474 Trace::Setter mci(traceMng(), _msgClassName());
475 VariableReaderMng var_read_mng(traceMng());
476 _buildFilteredVariableList(var_read_mng, filter);
477 OldDataReaderWrapper wrapper(reader);
478 _readVariablesData(var_read_mng, &wrapper);
479}
480
481/*---------------------------------------------------------------------------*/
482/*---------------------------------------------------------------------------*/
483
497{
499 if (!doc.get())
500 ARCANE_FATAL("The meta-data are invalid");
501 String hash_service_name;
502 JSONDocument json_reader;
503
504 XmlNode root_node = doc->documentNode().documentElement();
505 XmlNode json_node = root_node.child("json");
506
507 // Starting from Arcane version 3.11 (July 2023),
508 // metadata is also available in JSON format. We use it
509 // if 'm_is_use_json_metadata' is true.
510 JSONValue json_variables;
511 JSONValue json_meshes;
512 if (!json_node.null()) {
513 String json_meta_data = json_node.value();
514 info(6) << "READER_JSON=" << json_meta_data;
515 json_reader.parse(json_meta_data.bytes());
516
517 JSONValue json_meta_data_object = json_reader.root().expectedChild("arcane-checkpoint-metadata");
518
519 // Always reads the algorithm name even if metadata is not used
520 // because it is used for hash value comparisons.
521 String hash_algo_name = json_meta_data_object.child("hash-algorithm-name").value();
522 vmd_list.setHashAlgorithmName(hash_algo_name);
523
524 if (m_is_use_json_metadata) {
525 JSONValue json_version = json_meta_data_object.expectedChild("version");
526 Int32 v = json_version.valueAsInt32();
527 if (v != 1)
528 ARCANE_FATAL("Bad version for JSON Meta Data (v={0}). Only version '1' is supported", v);
529 json_variables = json_meta_data_object.expectedChild("variables");
530 json_meshes = json_meta_data_object.expectedChild("meshes");
531 }
532 }
533 XmlNode variables_node = root_node.child("variables");
534 _readVariablesMetaData(vmd_list, json_variables, variables_node);
535 XmlNode meshes_node = root_node.child("meshes");
536 _readMeshesMetaData(json_meshes, meshes_node);
537}
538
539/*---------------------------------------------------------------------------*/
540/*---------------------------------------------------------------------------*/
541
553{
554 ByteUniqueArray hash_values;
555 MD5HashAlgorithm md5_hash_algorithm;
556 SHA1HashAlgorithm sha1_hash_algorithm;
557 // By default, if nothing is specified, it is a protection from
558 // a version prior to 3.12 of Arcane. In this case, the algorithm
559 // used is 'MD5'.
560 IHashAlgorithm* hash_algo = &md5_hash_algorithm;
561 Ref<IHashAlgorithmContext> hash_context;
562 String hash_service_name = vmd_list.hashAlgorithmName();
563 if (!hash_service_name.empty()) {
564 if (hash_service_name == "MD5")
565 hash_algo = &md5_hash_algorithm;
566 else if (hash_service_name == "SHA1") {
567 hash_algo = &sha1_hash_algorithm;
568 hash_context = sha1_hash_algorithm.createContext();
569 }
570 else
571 ARCANE_FATAL("Not supported hash algorithm '{0}'. Valid values are 'SHA1' or 'MD5'");
572 }
573 Integer nb_error = 0;
574 IParallelMng* pm = m_variable_mng->m_parallel_mng;
575 Int32 sid = pm->commRank();
576 Directory listing_dir = m_variable_mng->subDomain()->listingDirectory();
577 for (const auto& i : vmd_list) {
578 const VariableMetaData* vmd = i.second.get();
579 Int32 hash_version = vmd->hashVersion();
580 String reference_hash = (hash_version > 0) ? vmd->hash2() : vmd->hash();
581 // Tests if the hash value is present. This is normally
582 // always the case, unless the protection comes from an old
583 // version of Arcane that did not save this information.
584 // This test can be removed later.
585 if (reference_hash.null())
586 continue;
587 const String& full_name = i.first;
588 IVariable* var = m_variable_mng->findVariableFullyQualified(full_name);
589 if (!var)
590 // Should not happen
591 continue;
592 hash_values.clear();
593 IData* data = var->data();
594 String hash_str;
595 bool do_compare = true;
596 if (hash_version > 0) {
597 ARCANE_CHECK_POINTER(hash_context.get());
598 hash_context->reset();
599 DataHashInfo hash_info(hash_context.get());
600 data->_commonInternal()->computeHash(hash_info);
601 HashAlgorithmValue hash_value;
602 hash_context->computeHashValue(hash_value);
603 hash_str = Convert::toHexaString(asBytes(hash_value.bytes()));
604 // Do not compare if the hash versions associated with the variable differ
605 if (hash_version != hash_info.version())
606 do_compare = false;
607 }
608 else {
609 data->computeHash(hash_algo, hash_values);
610 hash_str = Convert::toHexaString(hash_values);
611 }
612 if (do_compare && (hash_str != reference_hash)) {
613 ++nb_error;
614 error() << "Hash values are different. Corrumpted values."
615 << " name=" << var->fullName()
616 << " ref=" << reference_hash
617 << " current=" << hash_str;
619 Span<const Byte> buf(sdata->constBytes());
620 String fname = listing_dir.file(String::format("dump-{0}-sid_{1}", var->fullName(), sid));
621 std::ofstream ofile(fname.localstr());
622 ofile.write(reinterpret_cast<const char*>(buf.data()), buf.size());
623 }
624 }
625 Integer total_nb_error = pm->reduce(Parallel::ReduceSum, nb_error);
626 if (total_nb_error != 0) {
627 bool allow_bad = !platform::getEnvironmentVariable("ARCANE_ALLOW_DIFFERENT_CHECKPOINT_HASH").null();
628 if (!allow_bad)
629 throw ParallelFatalErrorException(A_FUNCINFO, "hash functions differs");
630 }
631}
632
633/*---------------------------------------------------------------------------*/
634/*---------------------------------------------------------------------------*/
635
636void VariableIOReaderMng::
637_createVariablesFromMetaData(const VariableMetaDataList& vmd_list)
638{
639 ISubDomain* sd = m_variable_mng->subDomain();
640 // Retrieves or builds variables that do not yet exist.
641 for (const auto& xvmd : vmd_list) {
642 auto& vmd = *(xvmd.second.get());
643 const String& full_name = vmd.fullName();
644 IVariable* var = m_variable_mng->findVariableFullyQualified(full_name);
645 if (var)
646 continue;
647 const String& base_name = vmd.baseName();
648 Integer property = vmd.property();
649 const String& mesh_name = vmd.meshName();
650 const String& group_name = vmd.itemGroupName();
651 const String& family_name = vmd.itemFamilyName();
652 VariableBuildInfo vbi(sd, base_name, property);
653 if (!mesh_name.null()) {
654 if (vmd.isPartial())
655 vbi = VariableBuildInfo(sd, base_name, mesh_name, family_name, group_name, property);
656 else
657 vbi = VariableBuildInfo(sd, base_name, mesh_name, family_name, property);
658 }
659 info(5) << "Create variable TYPE=" << full_name;
660 VariableRef* variable_ref = m_variable_mng->_createVariableFromType(vmd.fullType(), vbi);
661
662 if (vbi.property() & IVariable::PInShMem) {
663 IParallelMng* pm{};
664 // If the variable uses a mesh, it will be created by _readMeshesMetaData().
665 if (!mesh_name.null()) {
666 MeshHandle* mesh_handle = sd->meshMng()->findMeshHandle(mesh_name, true);
667 pm = mesh_handle->mesh()->parallelMng();
668 }
669 else {
670 pm = sd->parallelMng();
671 }
672 variable_ref->variable()->_internalApi()->changeAllocator(MemoryAllocationOptions(pm->_internalApi()->machineShMemWinMemoryAllocator()));
673 }
674 }
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
679
680void VariableIOReaderMng::
681_readVariablesMetaData(VariableMetaDataList& vmd_list, JSONValue variables_json,
682 const XmlNode& variables_node)
683{
684 String ustr_base_name("base-name");
685 String ustr_family_name("item-family-name");
686 String ustr_group_name("item-group-name");
687 String ustr_mesh_name("mesh-name");
688 String ustr_full_type("full-type");
689 String ustr_data_type("data-type");
690 String ustr_hash("hash");
691 String ustr_hash2("hash2");
692 String ustr_hash_version("hash-version");
693 String ustr_property("property");
694 String ustr_multitag("multi-tag");
695 vmd_list.clear();
696
697 struct VariableReadInfo
698 {
699 String full_type;
700 String base_name;
701 String mesh_name;
702 String family_name;
703 String group_name;
704 String hash_value;
705 String hash2_value;
706 Int32 hash_version = 0;
707 String multi_tag;
708 String data_type;
709 Int32 property = 0;
710 };
711 UniqueArray<VariableReadInfo> variables_info;
712
713 // Reads variable information from JSON data
714 // if it exists.
715 if (!variables_json.null()) {
716 // Reading via JSON
717 // Declares the list here to avoid returning a temporary in 'for-range'
718 JSONValueList vars = variables_json.valueAsArray();
719 for (const JSONValue& var : vars) {
720 VariableReadInfo r;
721 r.full_type = var.expectedChild(ustr_full_type).value();
722 r.base_name = var.expectedChild(ustr_base_name).value();
723 r.data_type = var.child(ustr_data_type).value();
724 r.mesh_name = var.child(ustr_mesh_name).value();
725 r.family_name = var.child(ustr_family_name).value();
726 r.group_name = var.child(ustr_group_name).value();
727 r.hash_value = var.child(ustr_hash).value();
728 r.hash2_value = var.child(ustr_hash2).value();
729 r.hash_version = var.child(ustr_hash_version).valueAsInt32();
730 r.multi_tag = var.child(ustr_multitag).value();
731 r.property = var.child(ustr_property).valueAsInt32();
732 variables_info.add(r);
733 }
734 }
735 else {
736 // Reading via XML data
737 XmlNodeList vars = variables_node.children("variable");
738 for (const auto& var : vars) {
739 VariableReadInfo r;
740 r.full_type = var.attrValue(ustr_full_type);
741 r.data_type = var.attrValue(ustr_data_type);
742 r.base_name = var.attrValue(ustr_base_name);
743 r.mesh_name = var.attrValue(ustr_mesh_name);
744 r.group_name = var.attrValue(ustr_group_name);
745 r.family_name = var.attrValue(ustr_family_name);
746 r.hash_value = var.attrValue(ustr_hash);
747 r.multi_tag = var.attrValue(ustr_multitag);
748 r.property = var.attr(ustr_property).valueAsInteger();
749 variables_info.add(r);
750 }
751 }
752
753 for (const VariableReadInfo& r : variables_info) {
754 String full_type = r.full_type;
755 VariableDataTypeInfo vdti(full_type);
756
757 // Checks that 'data-type' is consistent with the value in 'full_type'
758 if (vdti.dataTypeName() != r.data_type)
759 ARCANE_FATAL("Incoherent value for 'data-type' name v='{0}' expected='{1}'", r.data_type, vdti.dataTypeName());
760
761 String family_name = r.family_name;
762 // Currently, if the variable is not partial, its group
763 // is not saved in the metadata. It must therefore be generated.
764 String group_name = r.group_name;
765 bool is_partial = vdti.isPartial();
766 if (!is_partial) {
767 // NOTE: This construction must be consistent with that of
768 // DynamicMeshKindInfos. Eventually, the group name must always be saved
769 // in the metadata.
770 group_name = "All" + family_name + "s";
771 }
772 auto vmd = vmd_list.add(r.base_name, r.mesh_name, r.family_name, group_name, is_partial);
773
774 vmd->setFullType(full_type);
775 vmd->setHash(r.hash_value);
776 vmd->setHash2(r.hash2_value);
777 vmd->setHashVersion(r.hash_version);
778 vmd->setMultiTag(r.multi_tag);
779 vmd->setProperty(r.property);
780
781 info(5) << "CHECK VAR: "
782 << " base-name=" << vmd->baseName()
783 << " mesh-name=" << vmd->meshName()
784 << " family-name=" << vmd->itemFamilyName()
785 << " full-type=" << vmd->fullType()
786 << " name=" << vmd->fullName()
787 << " multitag=" << vmd->multiTag()
788 << " property=" << vmd->property()
789 << " hash=" << vmd->hash();
790 }
791}
792
793/*---------------------------------------------------------------------------*/
794/*---------------------------------------------------------------------------*/
795
796void VariableIOReaderMng::
797_readMeshesMetaData(JSONValue meshes_json, const XmlNode& meshes_node)
798{
799 ISubDomain* sd = m_variable_mng->subDomain();
800 IMeshMng* mesh_mng = sd->meshMng();
801 IMeshFactoryMng* mesh_factory_mng = mesh_mng->meshFactoryMng();
802
803 struct MeshInfo
804 {
805 String name;
806 String factory_name;
807 bool is_sequential;
808 };
809 UniqueArray<MeshInfo> meshes_info;
810
811 // Reads mesh information from JSON data
812 // if it exists.
813 if (!meshes_json.null()) {
814 // Declares the list here to avoid returning a temporary in 'for-range'
815 JSONValueList vars = meshes_json.valueAsArray();
816 for (const JSONValue& var : vars) {
817 String mesh_name = var.expectedChild("name").value();
818 String mesh_factory_name = var.child("factory-name").value();
819 bool is_sequential = false;
820 JSONValue v = var.child("sequential");
821 if (!v.null())
822 is_sequential = v.valueAsBool();
823 meshes_info.add({ mesh_name, mesh_factory_name, is_sequential });
824 }
825 }
826 else {
827 XmlNodeList meshes = meshes_node.children("mesh");
828 for (XmlNode var : meshes) {
829 String mesh_name = var.attrValue("name");
830 String mesh_factory_name = var.attrValue("factory-name");
831 bool is_sequential = var.attr("sequential", false).valueAsBoolean();
832 meshes_info.add({ mesh_name, mesh_factory_name, is_sequential });
833 }
834 }
835
836 for (const MeshInfo& mesh_info : meshes_info) {
837 String mesh_name = mesh_info.name;
838 String mesh_factory_name = mesh_info.factory_name;
839 MeshHandle* mesh_handle = mesh_mng->findMeshHandle(mesh_name, false);
840 IMesh* mesh = (mesh_handle) ? mesh_handle->mesh() : nullptr;
841 if (mesh)
842 continue;
843 bool is_sequential = mesh_info.is_sequential;
844 info() << "Creating from checkpoint mesh='" << mesh_name
845 << "' sequential?=" << is_sequential
846 << " factory=" << mesh_factory_name;
847 // Since April 2020, the 'factory-name' attribute must be present
848 // and its value non-null.
849 if (mesh_factory_name.null())
850 ARCANE_FATAL("No attribute 'factory-name' for mesh");
851
852 {
853 MeshBuildInfo mbi(mesh_name);
854 mbi.addFactoryName(mesh_factory_name);
855 IParallelMng* mesh_pm = m_variable_mng->m_parallel_mng;
856 if (is_sequential)
857 mesh_pm = mesh_pm->sequentialParallelMng();
858 mbi.addParallelMng(Arccore::makeRef(mesh_pm));
859 mesh_factory_mng->createMesh(mbi);
860 }
861 }
862}
863
864/*---------------------------------------------------------------------------*/
865/*---------------------------------------------------------------------------*/
866
867void VariableIOReaderMng::
868_buildFilteredVariableList(VariableReaderMng& var_read_mng, IVariableFilter* filter)
869{
870 VariableMetaDataList& vmd_list = var_read_mng.variableMetaDataList();
871 for (const auto& i : m_variable_mng->m_full_name_variable_map) {
872 IVariable* var = i.second;
873 bool apply_me = true;
874 if (filter)
875 apply_me = filter->applyFilter(*var);
876 info(5) << "Read variable name=" << var->fullName() << " filter=" << apply_me;
877 if (apply_me) {
878 Ref<VariableMetaData> vmd = var->createMetaDataRef();
879 vmd_list.add(vmd);
880 }
881 }
882}
883
884/*---------------------------------------------------------------------------*/
885/*---------------------------------------------------------------------------*/
886
887void VariableIOReaderMng::
888_readVariablesData(VariableReaderMng& var_read_mng, IDataReaderWrapper* reader)
889{
890 var_read_mng.readVariablesData(m_variable_mng, reader);
891 _finalizeReadVariables(var_read_mng.variablesToRead());
892}
893
894/*---------------------------------------------------------------------------*/
895/*---------------------------------------------------------------------------*/
896
897void VariableIOReaderMng::
898_finalizeReadVariables(const VariableList& vars_to_read)
899{
900 ARCANE_UNUSED(vars_to_read);
901
902 info(4) << "VariableMng: _finalizeReadVariables()";
903
904 // Resynchronize by reading the values of all variables to
905 // ensure that the references are still correct (in case of
906 // memory reallocation).
907 // NOTE: theoretically this should not be necessary because IVariable::notifyEndRead()
908 // handles this.
909 // NOTE: moreover, it is only necessary to do this for the variables
910 // in \a vars_to_read.
911 for (const auto& i : m_variable_mng->m_full_name_variable_map)
912 i.second->syncReferences();
913
914 // Notifies observers that a read has just been performed.
915 m_variable_mng->m_read_observable->notifyAllObservers();
916}
917
918/*---------------------------------------------------------------------------*/
919/*---------------------------------------------------------------------------*/
920
921} // End namespace Arcane
922
923/*---------------------------------------------------------------------------*/
924/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_CHECK_POINTER2(ptr, text)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
void clear()
Removes the elements from the array.
static std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Information for calculating data hash.
Data reading information.
Class managing a directory.
Definition Directory.h:36
String file(const String &file_name) const override
Returns the full path of the file file_name in the directory.
Definition Directory.cc:120
Hash algorithm return value.
virtual void computeHash(DataHashInfo &hash_info)=0
Calculates the hash of the data.
Interface for reading data of a variable (Version 2).
Interface for reading variable data.
Definition IDataReader.h:35
Interface of a data item.
Definition IData.h:34
virtual Ref< ISerializedData > createSerializedDataRef(bool use_basic_type) const =0
Serialize the data.
virtual void computeHash(IHashAlgorithm *algo, ByteArray &output) const =0
Compute a hash key on this data.
virtual IDataInternal * _commonInternal()=0
Interface of a hashing algorithm.
virtual IMeshFactoryMng * meshFactoryMng() const =0
Mesh factory associated with this manager.
virtual MeshHandle * findMeshHandle(const String &name, bool throw_exception)=0
Searches for the mesh with name name.
virtual IParallelMng * parallelMng()=0
Parallelism manager.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual IParallelMng * parallelMng()=0
Returns the parallelism manager.
virtual IMeshMng * meshMng() const =0
Returns the mesh manager.
Variable manager interface.
Interface of a variable.
Definition IVariable.h:40
virtual String fullName() const =0
Full variable name (with family prefix).
@ PInShMem
Indicates that the variable must be allocated in shared memory.
Definition IVariable.h:156
virtual IData * data()=0
Data associated with the variable.
static IXmlDocumentHolder * loadFromBuffer(Span< const Byte > buffer, const String &name, ITraceMng *tm)
Loads an XML document.
Definition DomUtils.cc:425
void parse(Span< const Byte > bytes)
Reads the file in UTF-8 format.
JSONValue root() const
Root element.
String value() const
Value in String format. The returned string is null if 'null()' is true.
Int32 valueAsInt32() const
Value in Int64 format. Returns 0 if 'null()' is true.
JSONValue expectedChild(StringView name) const
Child value with name name. Throws an exception if not found.
JSONValue child(StringView name) const
Child value with name name. Returns a null value if not found.
Calculates the MD5 hashing function of an array.
IMesh * mesh() const
Associated mesh.
Exception when a 'parallel' fatal error is generated.
T * get() const
Returns the object referenced by the instance.
Definition Ptr.h:122
void reset()
Positions the instance to the null pointer.
InstanceType * get() const
Associated instance or nullptr if none.
Reference to an instance.
Implementation of the SHA-1 algorithm.
Ref< IHashAlgorithmContext > createContext() override
Creates a context to calculate the hash value incrementally.
Encapsulation of an automatically destructing pointer.
Definition ScopedPtr.h:44
constexpr __host__ __device__ pointer data() const noexcept
Pointer to the start of the view.
Definition Span.h:539
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:327
View of an array of elements of type T.
Definition Span.h:635
bool null() const
Returns true if the string is null.
Definition String.cc:306
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
Span< const Byte > bytes() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:293
bool empty() const
True if the string is empty (null or "").
Definition String.cc:317
void split(StringContainer &str_array, char c) const
Splits the string based on the character c.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
ITraceMng * traceMng() const
Trace manager.
Parameters necessary for building a variable.
Data reading information for a variable.
Interface to use IDataReader or IDataReader2.
void _readMetaData(VariableMetaDataList &vmd_list, Span< const Byte > bytes)
Reading metadata.
void _checkHashFunction(const VariableMetaDataList &vmd_list)
Checks hash function values.
Metadata on a variable.
String hash() const
Hash of the variable in hexadecimal format.
String hash2() const
Hash of the variable in hexadecimal format.
Int32 hashVersion() const
Hash version (associated with hash2()).
Variable manager.
Definition VariableMng.h:57
Node of a DOM tree.
Definition XmlNode.h:51
XmlNode child(const String &name) const
Child node of this node with name name.
Definition XmlNode.cc:73
String value() const
Node value.
Definition XmlNode.cc:208
bool null() const
True if the node is null.
Definition XmlNode.h:303
String toHexaString(ByteConstArrayView input)
Converts a byte array to its hexadecimal representation.
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:335
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converts the view into an array of non-modifiable bytes.
Definition Span.h:1032
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.