Arcane  v4.1.5.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
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/* Classe gérant les entrées/sorties pour les 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: gérer le hash en version 64 bits.
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61namespace Arcane
62{
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67// Extraction des infos de type à partir d'une chaîne de caractères
68// NOTE L'extraction doit être cohérente avec la construction qui est
69// dans 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/*---------------------------------------------------------------------------*/
117{
118 public:
119
120 virtual ~IDataReaderWrapper() = default;
121
122 public:
123
124 virtual void beginRead(const VariableCollection& vars) = 0;
125 virtual void read(VariableMetaData* vmd, IVariable* var, IData* data) = 0;
126 virtual void endRead() = 0;
127};
128
129/*---------------------------------------------------------------------------*/
130/*---------------------------------------------------------------------------*/
135: public IDataReaderWrapper
136{
137 public:
138
139 explicit OldDataReaderWrapper(IDataReader* reader)
140 : m_reader(reader)
141 {}
142 void beginRead(const VariableCollection& vars) override
143 {
144 return m_reader->beginRead(vars);
145 }
146 void read(VariableMetaData* vmd, IVariable* var, IData* data) override
147 {
148 ARCANE_UNUSED(vmd);
149 m_reader->read(var, data);
150 }
151 void endRead() override
152 {
153 return m_reader->endRead();
154 }
155
156 private:
157
158 IDataReader* m_reader;
159};
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
167: public IDataReaderWrapper
168{
169 public:
170
171 explicit DataReaderWrapper(IDataReader2* reader)
172 : m_reader(reader)
173 {}
174 void beginRead(const VariableCollection& vars) override
175 {
176 ARCANE_UNUSED(vars);
177 return m_reader->beginRead(DataReaderInfo());
178 }
179 void read(VariableMetaData* vmd, IVariable* var, IData* data) override
180 {
181 ARCANE_UNUSED(var);
182 m_reader->read(VariableDataReadInfo(vmd, data));
183 }
184 void endRead() override
185 {
186 return m_reader->endRead();
187 }
188
189 private:
190
191 IDataReader2* m_reader;
192};
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
196
197class VariableMetaDataList
198{
199 public:
200
201 typedef std::map<String, Ref<VariableMetaData>> VMDMap;
202
203 public:
204
205 VariableMetaDataList() = default;
206 VariableMetaDataList(const VariableMetaDataList& rhs) = delete;
207 VariableMetaDataList& operator=(const VariableMetaDataList& rhs) = delete;
208 ~VariableMetaDataList()
209 {
210 clear();
211 }
212
213 public:
214
215 VariableMetaData* add(const String& base_name, const String& mesh_name,
216 const String& family_name, const String& group_name,
217 bool is_partial)
218 {
219 auto vmd = makeRef(new VariableMetaData(base_name, mesh_name, family_name, group_name, is_partial));
220 return add(vmd);
221 }
223 {
224 m_vmd_map.insert(std::make_pair(vmd->fullName(), vmd));
225 return vmd.get();
226 }
227 void clear()
228 {
229 m_vmd_map.clear();
230 }
231 VariableMetaData* findMetaData(const String& full_name)
232 {
233 auto x = m_vmd_map.find(full_name);
234 if (x != m_vmd_map.end())
235 return x->second.get();
236 return nullptr;
237 }
238 VMDMap::const_iterator begin() const { return m_vmd_map.begin(); }
239 VMDMap::const_iterator end() const { return m_vmd_map.end(); }
240 void setHashAlgorithmName(const String& v) { m_hash_algorithm = v; }
241 const String& hashAlgorithmName() const { return m_hash_algorithm; }
242
243 public:
244
245 std::map<String, Ref<VariableMetaData>> m_vmd_map;
246 String m_hash_algorithm;
247};
248
249/*---------------------------------------------------------------------------*/
250/*---------------------------------------------------------------------------*/
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
257class VariableReaderMng
258: public TraceAccessor
259{
260 struct VarReadInfo
261 {
262 public:
263
264 VarReadInfo(IVariable* var, IData* data, VariableMetaData* meta_data)
265 : m_variable(var)
266 , m_data(data)
267 , m_meta_data(meta_data)
268 {}
269
270 public:
271
272 IVariable* m_variable;
273 IData* m_data;
274 VariableMetaData* m_meta_data;
275 };
276
277 public:
278
279 explicit VariableReaderMng(ITraceMng* tm)
280 : TraceAccessor(tm)
281 {}
282
283 public:
284
285 void readVariablesData(IVariableMng* vm, VariableIOReaderMng::IDataReaderWrapper* reader);
286 VariableMetaDataList& variableMetaDataList() { return m_vmd_list; }
287 const VariableList& variablesToRead() { return m_vars_to_read; }
288
289 private:
290
291 VariableMetaDataList m_vmd_list;
292 VariableList m_vars_to_read;
293 UniqueArray<VarReadInfo> m_var_read_info_list;
294
295 private:
296
297 void _buildVariablesToRead(IVariableMng* vm);
298};
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
303void VariableReaderMng::
304_buildVariablesToRead(IVariableMng* vm)
305{
306 m_vars_to_read.clear();
307 m_var_read_info_list.clear();
308 for (const auto& x : m_vmd_list) {
309 const String& full_name = x.first;
310 IVariable* var = vm->findVariableFullyQualified(full_name);
311 if (!var)
312 ARCANE_FATAL("Var {0} not in VariableMng", full_name);
313 m_vars_to_read.add(var);
314 m_var_read_info_list.add(VarReadInfo(var, var->data(), x.second.get()));
315 }
316}
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
321void VariableReaderMng::
322readVariablesData(IVariableMng* vm, VariableIOReaderMng::IDataReaderWrapper* reader)
323{
324 _buildVariablesToRead(vm);
325 reader->beginRead(m_vars_to_read);
326 for (const auto& ivar : m_var_read_info_list) {
327 // NOTE: var peut-être nul
328 IVariable* var = ivar.m_variable;
329 IData* data = ivar.m_data;
330 VariableMetaData* vmd = ivar.m_meta_data;
331 String exception_message;
332 bool has_error = false;
333 try {
334 reader->read(vmd, var, data);
335 if (var)
336 var->notifyEndRead();
337 }
338 catch (const Exception& ex) {
339 OStringStream ostr;
340 ostr() << ex;
341 exception_message = ostr.str();
342 has_error = true;
343 }
344 catch (const std::exception& ex) {
345 exception_message = ex.what();
346 has_error = true;
347 }
348 if (has_error) {
349 OStringStream ostr;
350 String var_full_name = vmd->fullName();
351 ostr() << "Variable = " << var_full_name;
352 if (var) {
353 for (VarRefEnumerator ivar(var); ivar.hasNext(); ++ivar) {
354 VariableRef* ref = *ivar;
355 String s = ref->assignmentStackTrace();
356 if (!s.null())
357 ostr() << "Stack assignement: " << s;
358 }
359 }
360
361 ARCANE_FATAL("Can not read variable variable={0} exception={1} infos={2}",
362 var_full_name, exception_message, ostr.str());
363 }
364 }
365 reader->endRead();
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373
374VariableIOReaderMng::
375VariableIOReaderMng(VariableMng* vm)
376: TraceAccessor(vm->traceMng())
377, m_variable_mng(vm)
378, m_is_use_json_metadata(true)
379{
380 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_JSON_METADATA", true))
381 m_is_use_json_metadata = (v.value() != 0);
382}
383
384/*---------------------------------------------------------------------------*/
385/*---------------------------------------------------------------------------*/
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
389
390void VariableIOReaderMng::
391readCheckpoint(ICheckpointReader* service)
392{
393 Trace::Setter mci(traceMng(), _msgClassName());
394
395 if (!service)
396 ARCANE_FATAL("No protection service specified");
397
398 service->notifyBeginRead();
399
400 IDataReader* data_reader = service->dataReader();
401 if (!data_reader)
402 ARCANE_FATAL("no dataReader()");
403 String meta_data = data_reader->metaData();
404
405 if (meta_data.null())
406 ARCANE_FATAL("No meta-data in checkpoint.");
407
408 OldDataReaderWrapper wrapper(data_reader);
409
410 info(6) << "METADATA (ICheckpointReader): FromCheckpoint: " << meta_data;
411
412 VariableReaderMng var_read_mng(traceMng());
413 VariableMetaDataList& vmd_list = var_read_mng.variableMetaDataList();
414 {
415 _readMetaData(vmd_list, meta_data.bytes());
416 _createVariablesFromMetaData(vmd_list);
417 _readVariablesData(var_read_mng, &wrapper);
418 }
419
420 service->notifyEndRead();
421 _checkHashFunction(vmd_list);
422}
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427void VariableIOReaderMng::
428readCheckpoint(const CheckpointReadInfo& infos)
429{
430 Trace::Setter mci(traceMng(), _msgClassName());
431
432 ICheckpointReader2* service = infos.reader();
433 ARCANE_CHECK_POINTER2(service, "No checkpoint service specified");
434
435 IParallelMng* pm = infos.parallelMng();
436 ARCANE_CHECK_POINTER2(pm, "no parallelMng()");
437
438 service->notifyBeginRead(infos);
439
440 IDataReader2* data_reader = service->dataReader();
441 ARCANE_CHECK_POINTER2(data_reader, "No dataReader()");
442
443 UniqueArray<Byte> meta_data_bytes;
444 data_reader->fillMetaData(meta_data_bytes);
445 if (meta_data_bytes.empty())
446 ARCANE_FATAL("No meta-data in checkpoint.");
447
448 DataReaderWrapper wrapper(data_reader);
449
450 info(6) << "METADATA (ICheckpointReader2): FromCheckpoint: " << String(meta_data_bytes);
451
452 VariableReaderMng var_read_mng(traceMng());
453 VariableMetaDataList& vmd_list = var_read_mng.variableMetaDataList();
454 {
455 _readMetaData(vmd_list, meta_data_bytes);
456 _createVariablesFromMetaData(vmd_list);
457 _readVariablesData(var_read_mng, &wrapper);
458 }
459
460 service->notifyEndRead();
461 _checkHashFunction(vmd_list);
462}
463
464/*---------------------------------------------------------------------------*/
465/*---------------------------------------------------------------------------*/
466
467void VariableIOReaderMng::
468readVariables(IDataReader* reader, IVariableFilter* filter)
469{
470 Trace::Setter mci(traceMng(), _msgClassName());
471 VariableReaderMng var_read_mng(traceMng());
472 _buildFilteredVariableList(var_read_mng, filter);
473 OldDataReaderWrapper wrapper(reader);
474 _readVariablesData(var_read_mng, &wrapper);
475}
476
477/*---------------------------------------------------------------------------*/
478/*---------------------------------------------------------------------------*/
492{
494 if (!doc.get())
495 ARCANE_FATAL("The meta-data are invalid");
496 String hash_service_name;
497 JSONDocument json_reader;
498
499 XmlNode root_node = doc->documentNode().documentElement();
500 XmlNode json_node = root_node.child("json");
501
502 // A partir de la version 3.11 de Arcane (juillet 2023), les
503 // méta-données sont aussi disponibles au format JSON. On les utilise
504 // si 'm_is_use_json_metadata' est vrai.
505 JSONValue json_variables;
506 JSONValue json_meshes;
507 if (!json_node.null()) {
508 String json_meta_data = json_node.value();
509 info(6) << "READER_JSON=" << json_meta_data;
510 json_reader.parse(json_meta_data.bytes());
511
512 JSONValue json_meta_data_object = json_reader.root().expectedChild("arcane-checkpoint-metadata");
513
514 // Lit toujours le nom de l'algorithme même si on n'utilise pas les meta-données
515 // car on s'en sert pour les comparaisons de la valeur du hash.
516 String hash_algo_name = json_meta_data_object.child("hash-algorithm-name").value();
517 vmd_list.setHashAlgorithmName(hash_algo_name);
518
519 if (m_is_use_json_metadata) {
520 JSONValue json_version = json_meta_data_object.expectedChild("version");
521 Int32 v = json_version.valueAsInt32();
522 if (v != 1)
523 ARCANE_FATAL("Bad version for JSON Meta Data (v={0}). Only version '1' is supported", v);
524 json_variables = json_meta_data_object.expectedChild("variables");
525 json_meshes = json_meta_data_object.expectedChild("meshes");
526 }
527 }
528 XmlNode variables_node = root_node.child("variables");
529 _readVariablesMetaData(vmd_list, json_variables, variables_node);
530 XmlNode meshes_node = root_node.child("meshes");
531 _readMeshesMetaData(json_meshes, meshes_node);
532}
533
534/*---------------------------------------------------------------------------*/
535/*---------------------------------------------------------------------------*/
547{
548 ByteUniqueArray hash_values;
549 MD5HashAlgorithm md5_hash_algorithm;
550 SHA1HashAlgorithm sha1_hash_algorithm;
551 // Par défaut si rien n'est spécifié, il s'agit d'une protection issue
552 // d'une version antérieure à la 3.12 de Arcane. Dans ce cas l'algorithme
553 // utilisé est 'MD5'.
554 IHashAlgorithm* hash_algo = &md5_hash_algorithm;
555 Ref<IHashAlgorithmContext> hash_context;
556 String hash_service_name = vmd_list.hashAlgorithmName();
557 if (!hash_service_name.empty()) {
558 if (hash_service_name == "MD5")
559 hash_algo = &md5_hash_algorithm;
560 else if (hash_service_name == "SHA1") {
561 hash_algo = &sha1_hash_algorithm;
562 hash_context = sha1_hash_algorithm.createContext();
563 }
564 else
565 ARCANE_FATAL("Not supported hash algorithm '{0}'. Valid values are 'SHA1' or 'MD5'");
566 }
567 Integer nb_error = 0;
568 IParallelMng* pm = m_variable_mng->m_parallel_mng;
569 Int32 sid = pm->commRank();
570 Directory listing_dir = m_variable_mng->subDomain()->listingDirectory();
571 for (const auto& i : vmd_list) {
572 const VariableMetaData* vmd = i.second.get();
573 Int32 hash_version = vmd->hashVersion();
574 String reference_hash = (hash_version > 0) ? vmd->hash2() : vmd->hash();
575 // Teste si la valeur de hashage est présente. C'est normalement
576 // toujours le cas, sauf si la protection vient d'une ancienne
577 // version de Arcane qui ne sauvait pas cette information.
578 // Ce test pourra être supprimé plus tard.
579 if (reference_hash.null())
580 continue;
581 const String& full_name = i.first;
582 IVariable* var = m_variable_mng->findVariableFullyQualified(full_name);
583 if (!var)
584 // Ne devrait pas arriver
585 continue;
586 hash_values.clear();
587 IData* data = var->data();
588 String hash_str;
589 bool do_compare = true;
590 if (hash_version > 0) {
591 ARCANE_CHECK_POINTER(hash_context.get());
592 hash_context->reset();
593 DataHashInfo hash_info(hash_context.get());
594 data->_commonInternal()->computeHash(hash_info);
595 HashAlgorithmValue hash_value;
596 hash_context->computeHashValue(hash_value);
597 hash_str = Convert::toHexaString(asBytes(hash_value.bytes()));
598 // Ne compare si les versions de hash associées à la variable différent
599 if (hash_version != hash_info.version())
600 do_compare = false;
601 }
602 else {
603 data->computeHash(hash_algo, hash_values);
604 hash_str = Convert::toHexaString(hash_values);
605 }
606 if (do_compare && (hash_str != reference_hash)) {
607 ++nb_error;
608 error() << "Hash values are different. Corrumpted values."
609 << " name=" << var->fullName()
610 << " ref=" << reference_hash
611 << " current=" << hash_str;
613 Span<const Byte> buf(sdata->constBytes());
614 String fname = listing_dir.file(String::format("dump-{0}-sid_{1}", var->fullName(), sid));
615 std::ofstream ofile(fname.localstr());
616 ofile.write(reinterpret_cast<const char*>(buf.data()), buf.size());
617 }
618 }
619 Integer total_nb_error = pm->reduce(Parallel::ReduceSum, nb_error);
620 if (total_nb_error != 0) {
621 bool allow_bad = !platform::getEnvironmentVariable("ARCANE_ALLOW_DIFFERENT_CHECKPOINT_HASH").null();
622 if (!allow_bad)
623 throw ParallelFatalErrorException(A_FUNCINFO, "hash functions differs");
624 }
625}
626
627/*---------------------------------------------------------------------------*/
628/*---------------------------------------------------------------------------*/
629
630void VariableIOReaderMng::
631_createVariablesFromMetaData(const VariableMetaDataList& vmd_list)
632{
633 ISubDomain* sd = m_variable_mng->subDomain();
634 // Récupère ou construit les variables qui n'existent pas encore.
635 for (const auto& xvmd : vmd_list) {
636 auto& vmd = *(xvmd.second.get());
637 const String& full_name = vmd.fullName();
638 IVariable* var = m_variable_mng->findVariableFullyQualified(full_name);
639 if (var)
640 continue;
641 const String& base_name = vmd.baseName();
642 Integer property = vmd.property();
643 const String& mesh_name = vmd.meshName();
644 const String& group_name = vmd.itemGroupName();
645 const String& family_name = vmd.itemFamilyName();
646 VariableBuildInfo vbi(sd, base_name, property);
647 if (!mesh_name.null()) {
648 if (vmd.isPartial())
649 vbi = VariableBuildInfo(sd, base_name, mesh_name, family_name, group_name, property);
650 else
651 vbi = VariableBuildInfo(sd, base_name, mesh_name, family_name, property);
652 }
653 info(5) << "Create variable TYPE=" << full_name;
654 VariableRef* variable_ref = m_variable_mng->_createVariableFromType(vmd.fullType(), vbi);
655
656 if (vbi.property() & IVariable::PInShMem) {
657 IParallelMng* pm{};
658 // Si la variable utilise un maillage, il sera créé par _readMeshesMetaData().
659 if (!mesh_name.null()) {
660 MeshHandle* mesh_handle = sd->meshMng()->findMeshHandle(mesh_name, true);
661 pm = mesh_handle->mesh()->parallelMng();
662 }
663 else {
664 pm = sd->parallelMng();
665 }
666 variable_ref->variable()->_internalApi()->changeAllocator(MemoryAllocationOptions(pm->_internalApi()->machineShMemWinMemoryAllocator()));
667 }
668 }
669}
670
671/*---------------------------------------------------------------------------*/
672/*---------------------------------------------------------------------------*/
673
674void VariableIOReaderMng::
675_readVariablesMetaData(VariableMetaDataList& vmd_list, JSONValue variables_json,
676 const XmlNode& variables_node)
677{
678 String ustr_base_name("base-name");
679 String ustr_family_name("item-family-name");
680 String ustr_group_name("item-group-name");
681 String ustr_mesh_name("mesh-name");
682 String ustr_full_type("full-type");
683 String ustr_data_type("data-type");
684 String ustr_hash("hash");
685 String ustr_hash2("hash2");
686 String ustr_hash_version("hash-version");
687 String ustr_property("property");
688 String ustr_multitag("multi-tag");
689 vmd_list.clear();
690
691 struct VariableReadInfo
692 {
693 String full_type;
694 String base_name;
695 String mesh_name;
696 String family_name;
697 String group_name;
698 String hash_value;
699 String hash2_value;
700 Int32 hash_version = 0;
701 String multi_tag;
702 String data_type;
703 Int32 property = 0;
704 };
705 UniqueArray<VariableReadInfo> variables_info;
706
707 // Lit les informations des variables à partir des données JSON
708 // si ces dernières existent.
709 if (!variables_json.null()) {
710 // Lecture via JSON
711 // Déclare la liste ici pour éviter de retourner un temporaire dans 'for-range'
712 JSONValueList vars = variables_json.valueAsArray();
713 for (const JSONValue& var : vars) {
714 VariableReadInfo r;
715 r.full_type = var.expectedChild(ustr_full_type).value();
716 r.base_name = var.expectedChild(ustr_base_name).value();
717 r.data_type = var.child(ustr_data_type).value();
718 r.mesh_name = var.child(ustr_mesh_name).value();
719 r.family_name = var.child(ustr_family_name).value();
720 r.group_name = var.child(ustr_group_name).value();
721 r.hash_value = var.child(ustr_hash).value();
722 r.hash2_value = var.child(ustr_hash2).value();
723 r.hash_version = var.child(ustr_hash_version).valueAsInt32();
724 r.multi_tag = var.child(ustr_multitag).value();
725 r.property = var.child(ustr_property).valueAsInt32();
726 variables_info.add(r);
727 }
728 }
729 else {
730 // Lecture via les données XML
731 XmlNodeList vars = variables_node.children("variable");
732 for (const auto& var : vars) {
733 VariableReadInfo r;
734 r.full_type = var.attrValue(ustr_full_type);
735 r.data_type = var.attrValue(ustr_data_type);
736 r.base_name = var.attrValue(ustr_base_name);
737 r.mesh_name = var.attrValue(ustr_mesh_name);
738 r.group_name = var.attrValue(ustr_group_name);
739 r.family_name = var.attrValue(ustr_family_name);
740 r.hash_value = var.attrValue(ustr_hash);
741 r.multi_tag = var.attrValue(ustr_multitag);
742 r.property = var.attr(ustr_property).valueAsInteger();
743 variables_info.add(r);
744 }
745 }
746
747 for (const VariableReadInfo& r : variables_info) {
748 String full_type = r.full_type;
749 VariableDataTypeInfo vdti(full_type);
750
751 // Vérifie que 'data-type' est cohérent avec la valeur dans 'full_type'
752 if (vdti.dataTypeName() != r.data_type)
753 ARCANE_FATAL("Incoherent value for 'data-type' name v='{0}' expected='{1}'", r.data_type, vdti.dataTypeName());
754
755 String family_name = r.family_name;
756 // Actuellement, si la variable n'est pas partielle alors son groupe
757 // n'est pas sauvé dans les meta-données. Il faut donc le générer.
758 String group_name = r.group_name;
759 bool is_partial = vdti.isPartial();
760 if (!is_partial) {
761 // NOTE: Cette construction doit être cohérente avec celle de
762 // DynamicMeshKindInfos. A terme il faudra toujours sauver le nom du groupe
763 // dans les meta-données.
764 group_name = "All" + family_name + "s";
765 }
766 auto vmd = vmd_list.add(r.base_name, r.mesh_name, r.family_name, group_name, is_partial);
767
768 vmd->setFullType(full_type);
769 vmd->setHash(r.hash_value);
770 vmd->setHash2(r.hash2_value);
771 vmd->setHashVersion(r.hash_version);
772 vmd->setMultiTag(r.multi_tag);
773 vmd->setProperty(r.property);
774
775 info(5) << "CHECK VAR: "
776 << " base-name=" << vmd->baseName()
777 << " mesh-name=" << vmd->meshName()
778 << " family-name=" << vmd->itemFamilyName()
779 << " full-type=" << vmd->fullType()
780 << " name=" << vmd->fullName()
781 << " multitag=" << vmd->multiTag()
782 << " property=" << vmd->property()
783 << " hash=" << vmd->hash();
784 }
785}
786
787/*---------------------------------------------------------------------------*/
788/*---------------------------------------------------------------------------*/
789
790void VariableIOReaderMng::
791_readMeshesMetaData(JSONValue meshes_json, const XmlNode& meshes_node)
792{
793 ISubDomain* sd = m_variable_mng->subDomain();
794 IMeshMng* mesh_mng = sd->meshMng();
795 IMeshFactoryMng* mesh_factory_mng = mesh_mng->meshFactoryMng();
796
797 struct MeshInfo
798 {
799 String name;
800 String factory_name;
801 bool is_sequential;
802 };
803 UniqueArray<MeshInfo> meshes_info;
804
805 // Lit les informations des maillages à partir des données JSON
806 // si ces dernières existent.
807 if (!meshes_json.null()) {
808 // Déclare la liste ici pour éviter de retourner un temporaire dans 'for-range'
809 JSONValueList vars = meshes_json.valueAsArray();
810 for (const JSONValue& var : vars) {
811 String mesh_name = var.expectedChild("name").value();
812 String mesh_factory_name = var.child("factory-name").value();
813 bool is_sequential = false;
814 JSONValue v = var.child("sequential");
815 if (!v.null())
816 is_sequential = v.valueAsBool();
817 meshes_info.add({ mesh_name, mesh_factory_name, is_sequential });
818 }
819 }
820 else {
821 XmlNodeList meshes = meshes_node.children("mesh");
822 for (XmlNode var : meshes) {
823 String mesh_name = var.attrValue("name");
824 String mesh_factory_name = var.attrValue("factory-name");
825 bool is_sequential = var.attr("sequential", false).valueAsBoolean();
826 meshes_info.add({ mesh_name, mesh_factory_name, is_sequential });
827 }
828 }
829
830 for (const MeshInfo& mesh_info : meshes_info) {
831 String mesh_name = mesh_info.name;
832 String mesh_factory_name = mesh_info.factory_name;
833 MeshHandle* mesh_handle = mesh_mng->findMeshHandle(mesh_name, false);
834 IMesh* mesh = (mesh_handle) ? mesh_handle->mesh() : nullptr;
835 if (mesh)
836 continue;
837 bool is_sequential = mesh_info.is_sequential;
838 info() << "Creating from checkpoint mesh='" << mesh_name
839 << "' sequential?=" << is_sequential
840 << " factory=" << mesh_factory_name;
841 // Depuis avril 2020, l'attribut 'factory-name' doit être présent
842 // et sa valeur non nulle.
843 if (mesh_factory_name.null())
844 ARCANE_FATAL("No attribute 'factory-name' for mesh");
845
846 {
847 MeshBuildInfo mbi(mesh_name);
848 mbi.addFactoryName(mesh_factory_name);
849 IParallelMng* mesh_pm = m_variable_mng->m_parallel_mng;
850 if (is_sequential)
851 mesh_pm = mesh_pm->sequentialParallelMng();
852 mbi.addParallelMng(Arccore::makeRef(mesh_pm));
853 mesh_factory_mng->createMesh(mbi);
854 }
855 }
856}
857
858/*---------------------------------------------------------------------------*/
859/*---------------------------------------------------------------------------*/
860
861void VariableIOReaderMng::
862_buildFilteredVariableList(VariableReaderMng& var_read_mng, IVariableFilter* filter)
863{
864 VariableMetaDataList& vmd_list = var_read_mng.variableMetaDataList();
865 for (const auto& i : m_variable_mng->m_full_name_variable_map) {
866 IVariable* var = i.second;
867 bool apply_me = true;
868 if (filter)
869 apply_me = filter->applyFilter(*var);
870 info(5) << "Read variable name=" << var->fullName() << " filter=" << apply_me;
871 if (apply_me) {
872 Ref<VariableMetaData> vmd = var->createMetaDataRef();
873 vmd_list.add(vmd);
874 }
875 }
876}
877
878/*---------------------------------------------------------------------------*/
879/*---------------------------------------------------------------------------*/
880
881void VariableIOReaderMng::
882_readVariablesData(VariableReaderMng& var_read_mng, IDataReaderWrapper* reader)
883{
884 var_read_mng.readVariablesData(m_variable_mng, reader);
885 _finalizeReadVariables(var_read_mng.variablesToRead());
886}
887
888/*---------------------------------------------------------------------------*/
889/*---------------------------------------------------------------------------*/
890
891void VariableIOReaderMng::
892_finalizeReadVariables(const VariableList& vars_to_read)
893{
894 ARCANE_UNUSED(vars_to_read);
895
896 info(4) << "VariableMng: _finalizeReadVariables()";
897
898 // Resynchronise en lecture les valeurs de toutes les variables pour
899 // être sur que les références sont toujours correctes (en cas de
900 // réallocation mémoire).
901 // NOTE: en théorie cela ne doit pas être utile car IVariable::notifyEndRead()
902 // se charge de faire cela.
903 // NOTE: de plus, il n'est nécessaire de le faire que sur les variables
904 // de \a vars_to_read.
905 for (const auto& i : m_variable_mng->m_full_name_variable_map)
906 i.second->syncReferences();
907
908 // Notifie les observateurs qu'une lecture vient d'être faite.
909 m_variable_mng->m_read_observable->notifyAllObservers();
910}
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
914
915} // End namespace Arcane
916
917/*---------------------------------------------------------------------------*/
918/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_CHECK_POINTER2(ptr, text)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
void clear()
Supprime les éléments du tableau.
static ARCCORE_BASE_EXPORT std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Informations pour le calcul du hash d'une donnée.
Informations de relecture des données.
Classe gérant un répertoire.
Definition Directory.h:35
String file(const String &file_name) const override
Retourne le chemin complet du fichier file_name dans le répertoire.
Definition Directory.cc:120
Valeur retournée par un algorithme de hashage.
virtual void computeHash(DataHashInfo &hash_info)=0
Calcule le hash de la donnée.
Interface de lecture des données d'une variable (Version 2)
Interface de lecture des données d'une variable.
Definition IDataReader.h:34
Interface d'une donnée.
Definition IData.h:33
virtual Ref< ISerializedData > createSerializedDataRef(bool use_basic_type) const =0
Sérialise la donnée.
virtual void computeHash(IHashAlgorithm *algo, ByteArray &output) const =0
Calcul une clé de hashage sur cette donnée.
virtual IDataInternal * _commonInternal()=0
Interface d'un algorithme de hashage.
virtual IMeshFactoryMng * meshFactoryMng() const =0
Fabrique de maillages associée à ce gestionnaire.
virtual MeshHandle * findMeshHandle(const String &name, bool throw_exception)=0
Recherche le maillage de nom name.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual IParallelMng * parallelMng()=0
Retourne le gestionnaire de parallélisme.
virtual IMeshMng * meshMng() const =0
Retourne le gestionnaire de maillage.
Interface du gestionnaire de traces.
Interface du gestionnaire de variables.
Interface d'une variable.
Definition IVariable.h:39
virtual String fullName() const =0
Nom complet de la variable (avec le préfixe de la famille)
@ PInShMem
Indique que la variable doit être alloué en mémoire partagée.
Definition IVariable.h:153
virtual IData * data()=0
Données associées à la variable.
static IXmlDocumentHolder * loadFromBuffer(Span< const Byte > buffer, const String &name, ITraceMng *tm)
Charge un document XML.
Definition DomUtils.cc:426
void parse(Span< const Byte > bytes)
Lit le fichier au format UTF-8.
JSONValue root() const
Elément racine.
String value() const
Valeur sous forme de String. La chaîne retournée est nulle si 'null()' est vrai.
Int32 valueAsInt32() const
Valeur sous forme de Int64. Retourn 0 si 'null()' est vrai.
JSONValue expectedChild(StringView name) const
Valeur fille de nom name. Lance une exception si non trouvé.
JSONValue child(StringView name) const
Valeur fille de nom name. Retourne une valeur nulle si non trouvé.
Calcule la fonction de hashage MD5 d'un tableau.
IMesh * mesh() const
Maillage associé.
Exception lorsqu'une erreur fatale 'parallèle' est générée.
T * get() const
Retourne l'objet référé par l'instance.
Definition Ptr.h:121
Référence à une instance.
void reset()
Positionne l'instance au pointeur nul.
InstanceType * get() const
Instance associée ou nullptr si aucune.
Implémentation de l'algorithme SHA-1.
Ref< IHashAlgorithmContext > createContext() override
Créé un contexte pour calculer la valeur du hash de manière incrémentale.
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
Definition Span.h:537
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:325
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:305
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
Span< const Byte > bytes() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:292
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
Definition String.cc:316
void split(StringContainer &str_array, char c) const
Découpe la chaîne suivant le caractère c.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
ITraceMng * traceMng() const
Gestionnaire de trace.
Paramètres nécessaires à la construction d'une variable.
Collection de variables.
Informations de relecture des données d'une variable.
Interface pour utiliser IDataReader ou IDataReader2.
void _readMetaData(VariableMetaDataList &vmd_list, Span< const Byte > bytes)
Lecture des méta-données.
void _checkHashFunction(const VariableMetaDataList &vmd_list)
Vérifie les valeurs des fonctions de hashage.
Meta-données sur une variable.
String hash() const
Hash de la variable sous forme de hexadécimale.
String hash2() const
Hash de la variable sous forme de hexadécimale.
Int32 hashVersion() const
Version du hash (associé à hash2())
Gestionnaire de variables.
Definition VariableMng.h:56
Noeud d'un arbre DOM.
Definition XmlNode.h:51
XmlNode child(const String &name) const
Noeud fils de celui-ci de nom name.
Definition XmlNode.cc:64
String value() const
Valeur du noeud.
Definition XmlNode.cc:199
bool null() const
Vrai si le noeud est nul.
Definition XmlNode.h:294
String toHexaString(ByteConstArrayView input)
Converti un tableau d'octet en sa représentation hexadécimale.
@ ReduceSum
Somme des valeurs.
ARCCORE_BASE_EXPORT String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
UniqueArray< Byte > ByteUniqueArray
Tableau dynamique à une dimension de caractères.
Definition UtilsTypes.h:335
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets non modifiables.
Definition Span.h:1022
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.