Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
BasicReaderWriterDatabase.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/* BasicReaderWriterDatabase.cc (C) 2000-2025 */
9/* */
10/* Database for the 'BasicReaderWriter' service. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/std/internal/BasicReaderWriterDatabase.h"
15
16#include "arcane/utils/Array.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/Ref.h"
19#include "arcane/utils/FatalErrorException.h"
20#include "arcane/utils/JSONReader.h"
21#include "arcane/utils/JSONWriter.h"
22#include "arcane/utils/CheckedConvert.h"
23#include "arcane/utils/IDataCompressor.h"
24#include "arcane/utils/SmallArray.h"
25#include "arcane/utils/IHashAlgorithm.h"
26#include "arcane/utils/ITraceMng.h"
27
28#include "arcane/core/ArcaneException.h"
29
30#include "arcane/std/internal/TextReader2.h"
31#include "arcane/std/internal/TextWriter2.h"
32#include "arcane/std/internal/IHashDatabase.h"
33
34#include <fstream>
35#include <map>
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40namespace Arcane::impl
41{
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
47class Hasher
48{
49 public:
50
51 void computeHash(Span<const std::byte> bytes, Array<Byte>& hash_result)
52 {
53 ARCANE_CHECK_POINTER(m_hash_algorithm);
54 {
56 m_nb_processed_bytes += bytes.size();
57 m_hash_algorithm->computeHash64(bytes, hash_result);
59 m_hash_time += (t2 - t1);
60 }
61 }
62
63 void setHashAlgorithm(IHashAlgorithm* algo)
64 {
65 m_hash_algorithm = algo;
66 }
67
68 void printStats(ITraceMng* tm)
69 {
70 if (m_nb_processed_bytes == 0)
71 return;
72 Real nb_byte_per_second = static_cast<Real>(m_nb_processed_bytes) / (m_hash_time + 1.0e-9);
73 // To get Mega-bytes per second
74 nb_byte_per_second /= 1.0e6;
75 tm->info() << "Hasher:nb_processed=" << m_nb_processed_bytes
76 << " hash_time=" << m_hash_time
77 << " rate=" << static_cast<Int64>(nb_byte_per_second) << " MB/s"
78 << "\n";
79 }
80
81 private:
82
83 IHashAlgorithm* m_hash_algorithm = nullptr;
84 Int64 m_nb_processed_bytes = 0;
85 Real m_hash_time = 0.0;
86};
87
88/*---------------------------------------------------------------------------*/
89/*---------------------------------------------------------------------------*/
90
92class BasicReaderWriterDatabaseEpilogFormat
93{
94 public:
95
96 // The size of this structure must not be modified under penalty
97 // of making the format incompatible. To support evolution, we fix
98 // a size of 128 bytes, i.e., 16 'Int64'
99 static constexpr Int64 STRUCT_SIZE = 128;
100
101 public:
102
103 BasicReaderWriterDatabaseEpilogFormat()
104 {
105 checkStructureSize();
106 for (int i = 0; i < 10; ++i)
107 m_remaining_padding[i] = i;
108 }
109
110 public:
111
112 void setJSONDataInfoOffsetAndSize(Int64 file_offset, Int64 data_size)
113 {
114 m_json_data_info_file_offset = file_offset;
115 m_json_data_info_size = data_size;
116 }
117 Int32 version() const { return m_version; }
118 Int64 jsonDataInfoFileOffset() const { return m_json_data_info_file_offset; }
119 Int64 jsonDataInfoSize() const { return m_json_data_info_size; }
120 Span<std::byte> bytes()
121 {
122 return { reinterpret_cast<std::byte*>(this), STRUCT_SIZE };
123 }
124
125 private:
126
127 // Epilogue version. Must not be confused with the file version
128 // which is in the header.
129 Int32 m_version = 1;
130 Int32 m_padding0 = 0;
131 Int64 m_padding1 = 0;
132 Int64 m_padding2 = 0;
133 Int64 m_padding3 = 0;
134 Int64 m_json_data_info_file_offset = -1;
135 Int64 m_json_data_info_size = 0;
136 Int64 m_remaining_padding[10];
137
138 public:
139
140 static void checkStructureSize()
141 {
142 Int64 s = sizeof(BasicReaderWriterDatabaseEpilogFormat);
143 if (s != STRUCT_SIZE)
144 ARCANE_FATAL("Invalid size for epilog format size={0} expected={1}", s, STRUCT_SIZE);
145 }
146};
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
152class BasicReaderWriterDatabaseHeaderFormat
153{
154 public:
155
156 // The size of this structure must not be modified under penalty
157 // of making the format incompatible. To support evolution, we fix
158 // a size of 128 bytes, i.e., 16 'Int64'
159 static constexpr Int64 STRUCT_SIZE = 128;
160
161 public:
162
163 BasicReaderWriterDatabaseHeaderFormat()
164 {
165 checkStructureSize();
166 for (int i = 0; i < 12; ++i)
167 m_remaining_padding[i] = i;
168 }
169
170 public:
171
172 Span<std::byte> bytes()
173 {
174 return { reinterpret_cast<std::byte*>(this), STRUCT_SIZE };
175 }
176 void setVersion(Int32 version) { m_version = version; }
177 Int32 version() const { return m_version; }
178 void checkHeader()
179 {
180 // Checks that the header is correct.
181 if (m_header_begin[0] != 'A' || m_header_begin[1] != 'C' || m_header_begin[2] != 'R' || m_header_begin[3] != (Byte)39)
182 ARCANE_FATAL("Bad header");
183 // TODO: test endianness
184 }
185
186 private:
187
188 // First 4 bytes to indicate that it is an Arcane Checkpoint Restart file
189 std::array<Byte, 4> m_header_begin = { 'A', 'C', 'R', 39 };
190 // Next 4 bytes to indicate endianness (not yet used)
191 Int32 m_endian_int = 0x01020304;
192 // File version (to be modified by the caller via setVersion())
193 Int32 m_version = 0;
194 Int32 m_padding0 = 0;
195 Int64 m_padding1 = 0;
196 Int64 m_padding2 = 0;
197 Int64 m_remaining_padding[12];
198
199 public:
200
201 static void checkStructureSize()
202 {
203 Int64 s = sizeof(BasicReaderWriterDatabaseHeaderFormat);
204 if (s != STRUCT_SIZE)
205 ARCANE_FATAL("Invalid size for header format size={0} expected={1}", s, STRUCT_SIZE);
206 }
207};
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211
212class BasicReaderWriterDatabaseCommon
213: public TraceAccessor
214{
215 public:
216
218 {
219 static constexpr int MAX_SIZE = 8;
220 void fill(SmallSpan<const Int64> v)
221 {
222 nb = v.size();
223 if (nb > MAX_SIZE) {
224 m_large_extents = v;
225 return;
226 }
227 for (Int32 i = 0; i < nb; ++i)
228 sizes[i] = v[i];
229 }
230 Int64ConstArrayView view() const
231 {
232 if (nb <= MAX_SIZE)
233 return Int64ConstArrayView(nb, sizes);
234 return m_large_extents.view();
235 }
236 Int32 size() const { return nb; }
237
238 private:
239
240 Int32 nb = 0;
241
242 public:
243
244 Int64 sizes[MAX_SIZE];
245 UniqueArray<Int64> m_large_extents;
246 };
247
248 struct DataInfo
249 {
250 Int64 m_file_offset = 0;
251 ExtentsInfo m_extents;
252 };
253
254 public:
255
256 BasicReaderWriterDatabaseCommon(ITraceMng* tm, Int32 version)
257 : TraceAccessor(tm)
258 {
259 if (version >= 3) {
260 String hash_directory = platform::getEnvironmentVariable("ARCANE_HASHDATABASE_DIRECTORY");
261 if (!hash_directory.null()) {
262 info() << "Using Hash database at location '" << hash_directory << "'";
263 m_hash_database = createFileHashDatabase(tm, hash_directory);
264 }
265 else {
266 String redis_machine = platform::getEnvironmentVariable("ARCANE_HASHDATABASE_REDIS");
267 if (!redis_machine.null()) {
268 info() << "Using Redis database at location '" << redis_machine << "'";
269 m_hash_database = createRedisHashDatabase(tm, redis_machine, 6379);
270 }
271 }
272 }
273 }
274
275 public:
276
277 DataInfo& findData(const String& key_name)
278 {
279 auto x = m_data_infos.find(key_name);
280 if (x == m_data_infos.end())
281 ARCANE_FATAL("Can not find key '{0}' in database", key_name);
282 return x->second;
283 }
284
285 public:
286
287 std::map<String, DataInfo> m_data_infos;
288 Ref<IDataCompressor> m_data_compressor;
289 Ref<IHashAlgorithm> m_hash_algorithm;
290 Ref<IHashDatabase> m_hash_database;
291};
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
295
296/*---------------------------------------------------------------------------*/
297/*---------------------------------------------------------------------------*/
298
300: public BasicReaderWriterDatabaseCommon
301{
302 public:
303
304 Impl(ITraceMng* tm, const String& filename, Int32 version)
305 : BasicReaderWriterDatabaseCommon(tm, version)
306 , m_writer(filename)
307 , m_version(version)
308 {
309 if (m_version >= 3)
310 _writeHeader();
311 }
312
313 ~Impl()
314 {
315 if (m_version >= 3)
316 arcaneCallFunctionAndTerminateIfThrow([&]() { _writeEpilog(); });
317 m_hasher.printStats(traceMng());
318 }
319
320 public:
321
322 Int64 fileOffset() { return m_writer.fileOffset(); }
323 void setExtents(const String& key_name, SmallSpan<const Int64> extents);
324 void write(const String& key, Span<const std::byte> values);
325
326 private:
327
328 void _addKey(const String& key, SmallSpan<const Int64> extents);
329 void _writeKey(const String& key);
330 void _writeHeader();
331 void _writeEpilog();
332
333 public:
334
335 TextWriter2 m_writer;
336 Int32 m_version;
337 Hasher m_hasher;
338
339 private:
340
341 void _write2(const String& key, Span<const std::byte> values);
342};
343
344/*---------------------------------------------------------------------------*/
345/*---------------------------------------------------------------------------*/
346
347KeyValueTextWriter::
348KeyValueTextWriter(ITraceMng* tm, const String& filename, Int32 version)
349: TraceAccessor(tm)
350, m_p(new Impl(tm, filename, version))
351{
352}
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
356
357KeyValueTextWriter::
358~KeyValueTextWriter()
359{
360 delete m_p;
361}
362
363/*---------------------------------------------------------------------------*/
364/*---------------------------------------------------------------------------*/
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
377{
379
380 // Currently, if we enter this part of the code,
381 // the version used is 3 or higher.
382 header.setVersion(m_version);
383 binaryWrite(m_writer.stream(), header.bytes());
384}
385
386/*---------------------------------------------------------------------------*/
387/*---------------------------------------------------------------------------*/
388
389void KeyValueTextWriter::Impl::
390_writeEpilog()
391{
392 // Writes metadata in JSON format.
393 JSONWriter jsw;
394 {
395 JSONWriter::Object main_object(jsw);
396 jsw.writeKey("Data");
397 jsw.beginArray();
398 for (auto& x : m_data_infos) {
399 JSONWriter::Object o(jsw);
400 jsw.write("Name", x.first);
401 jsw.write("FileOffset", x.second.m_file_offset);
402 jsw.write("Extents", x.second.m_extents.view());
403 }
404 jsw.endArray();
405 }
406
407 std::ostream& stream = m_writer.stream();
408
409 // Stores the file position of the metadata
410 // as well as their size.
411 Int64 file_offset = m_writer.fileOffset();
412 StringView buf = jsw.getBuffer();
413 Int64 meta_data_size = buf.size();
414
415 binaryWrite(stream, asBytes(buf.bytes()));
416
417 {
419 epilog.setJSONDataInfoOffsetAndSize(file_offset, meta_data_size);
420 // Must always be the last write in the file
421 binaryWrite(stream, epilog.bytes());
422 }
423}
424
425/*---------------------------------------------------------------------------*/
426/*---------------------------------------------------------------------------*/
427
428void KeyValueTextWriter::Impl::
429setExtents(const String& key_name, SmallSpan<const Int64> extents)
430{
431 if (m_version >= 3) {
432 _addKey(key_name, extents);
433 }
434 else {
435 // Versions 1 and 2.
436 // The dimension values are saved directly to the file at the current position
437 // The number of values is given by the size
438 // of \a extents
439 Integer dimension_array_size = extents.size();
440 if (dimension_array_size != 0) {
441 String true_key_name = "Extents:" + key_name;
442 String comment = String::format("Writing Dim1Size for '{0}'", key_name);
443 if (m_version == 1) {
444 // Saves dimensions as an array of Int32
445 UniqueArray<Integer> dims(dimension_array_size);
446 for (Integer i = 0; i < dimension_array_size; ++i)
447 dims[i] = CheckedConvert::toInteger(extents[i]);
448 m_writer.write(asBytes(dims));
449 }
450 else
451 // Saves dimensions as an array of Int64
452 m_writer.write(asBytes(extents));
453 }
454 }
455}
456
457/*---------------------------------------------------------------------------*/
458/*---------------------------------------------------------------------------*/
459
460void KeyValueTextWriter::Impl::
461write(const String& key, Span<const std::byte> values)
462{
463 _writeKey(key);
464
465 IDataCompressor* d = m_data_compressor.get();
466 Int64 len = values.size();
467 if (d && len > d->minCompressSize()) {
468 UniqueArray<std::byte> compressed_values;
469 m_data_compressor->compress(values, compressed_values);
470 Int64 compressed_size = compressed_values.largeSize();
471 m_writer.write(asBytes(Span<const Int64>(&compressed_size, 1)));
472 _write2(key, compressed_values);
473 }
474 else
475 _write2(key, values);
476}
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
480
481void KeyValueTextWriter::Impl::
482_write2(const String& key, Span<const std::byte> values)
483{
484 if (m_hash_database.get()) {
485 IHashAlgorithm* hash_algo = m_hash_algorithm.get();
486 if (!hash_algo)
487 ARCANE_FATAL("Can not use hash database without hash algorithm");
488
489 SmallArray<Byte, 1024> hash_result;
490 m_hasher.computeHash(values, hash_result);
491 String hash_value = Convert::toHexaString(hash_result);
492
493 HashDatabaseWriteResult result;
494 HashDatabaseWriteArgs args(values, hash_value);
495 args.setKey(key);
496
497 m_hash_database->writeValues(args, result);
498 info(5) << "WRITE_KW_HASH key=" << key << " hash=" << hash_value << " len=" << values.size();
499 m_writer.write(asBytes(hash_result));
500 }
501 else
502 m_writer.write(values);
503}
504
505/*---------------------------------------------------------------------------*/
506/*---------------------------------------------------------------------------*/
507
508String KeyValueTextWriter::
509fileName() const
510{
511 return m_p->m_writer.fileName();
512}
513
514/*---------------------------------------------------------------------------*/
515/*---------------------------------------------------------------------------*/
516
517void KeyValueTextWriter::
518setDataCompressor(Ref<IDataCompressor> ds)
519{
520 m_p->m_data_compressor = ds;
521}
522
523/*---------------------------------------------------------------------------*/
524/*---------------------------------------------------------------------------*/
525
526Ref<IDataCompressor> KeyValueTextWriter::
527dataCompressor() const
528{
529 return m_p->m_data_compressor;
530}
531
532/*---------------------------------------------------------------------------*/
533/*---------------------------------------------------------------------------*/
534
535void KeyValueTextWriter::
536setHashAlgorithm(Ref<IHashAlgorithm> v)
537{
538 m_p->m_hash_algorithm = v;
539 m_p->m_hasher.setHashAlgorithm(v.get());
540}
541
542/*---------------------------------------------------------------------------*/
543/*---------------------------------------------------------------------------*/
544
545Ref<IHashAlgorithm> KeyValueTextWriter::
546hashAlgorithm() const
547{
548 return m_p->m_hash_algorithm;
549}
550
551/*---------------------------------------------------------------------------*/
552/*---------------------------------------------------------------------------*/
553
554Int64 KeyValueTextWriter::
555fileOffset()
556{
557 return m_p->m_writer.fileOffset();
558}
559
560/*---------------------------------------------------------------------------*/
561/*---------------------------------------------------------------------------*/
562
563void KeyValueTextWriter::Impl::
564_addKey(const String& key, SmallSpan<const Int64> extents)
565{
567 d.m_extents.fill(extents);
568 m_data_infos.insert(std::make_pair(key, d));
569}
570
571/*---------------------------------------------------------------------------*/
572/*---------------------------------------------------------------------------*/
573
574void KeyValueTextWriter::Impl::
575_writeKey(const String& key)
576{
577 if (m_version >= 3) {
578 auto x = m_data_infos.find(key);
579 if (x == m_data_infos.end())
580 ARCANE_FATAL("Key '{0}' is not in map. You should call setExtents() before", key);
581 x->second.m_file_offset = fileOffset();
582 }
583}
584
585/*---------------------------------------------------------------------------*/
586/*---------------------------------------------------------------------------*/
587
588/*---------------------------------------------------------------------------*/
589/*---------------------------------------------------------------------------*/
590
591void KeyValueTextWriter::
592setExtents(const String& key_name, SmallSpan<const Int64> extents)
593{
594 m_p->setExtents(key_name, extents);
595}
596
597/*---------------------------------------------------------------------------*/
598/*---------------------------------------------------------------------------*/
599
600void KeyValueTextWriter::
601write(const String& key, Span<const std::byte> values)
602{
603 m_p->write(key, values);
604}
605
606/*---------------------------------------------------------------------------*/
607/*---------------------------------------------------------------------------*/
608
609/*---------------------------------------------------------------------------*/
610/*---------------------------------------------------------------------------*/
611
613: public BasicReaderWriterDatabaseCommon
614{
615 public:
616
617 Impl(ITraceMng* tm, const String& filename, Int32 version)
618 : BasicReaderWriterDatabaseCommon(tm, version)
619 , m_reader(filename)
620 , m_version(version)
621 {
622 if (m_version >= 3) {
623 _readHeader();
624 _readJSON();
625 }
626 }
627
628 public:
629
630 void readIntegers(const String& key, Span<Integer> values);
631 void read(const String& key, Span<std::byte> values);
632
633 public:
634
635 void _readHeader();
636 void _readJSON();
637 void _readDirect(Int64 offset, Span<std::byte> bytes);
638 void _setFileOffset(const String& key_name);
639 void _read2(const String& key_name, Span<std::byte> values);
640
641 public:
642
643 TextReader2 m_reader;
644 Int32 m_version;
645};
646
647/*---------------------------------------------------------------------------*/
648/*---------------------------------------------------------------------------*/
649
650KeyValueTextReader::
651KeyValueTextReader(ITraceMng* tm, const String& filename, Int32 version)
652: TraceAccessor(tm)
653, m_p(new Impl(tm, filename, version))
654{
655}
656
657/*---------------------------------------------------------------------------*/
658/*---------------------------------------------------------------------------*/
659
660KeyValueTextReader::
661~KeyValueTextReader()
662{
663 delete m_p;
664}
665
666/*---------------------------------------------------------------------------*/
667/*---------------------------------------------------------------------------*/
668
669void KeyValueTextReader::Impl::
670_readDirect(Int64 offset, Span<std::byte> bytes)
671{
672 m_reader.setFileOffset(offset);
673 std::istream& s = m_reader.stream();
674 binaryRead(s, bytes);
675 if (s.fail())
676 ARCANE_FATAL("Can not read file part offset={0} length={1}", offset, bytes.length());
677}
678
679/*---------------------------------------------------------------------------*/
680/*---------------------------------------------------------------------------*/
681
690{
692 Span<std::byte> bytes(header.bytes());
693 _readDirect(0, bytes);
694 header.checkHeader();
695 Int32 version = header.version();
696 if (version != m_version)
697 ARCANE_FATAL("Invalid version for ACR file version={0} expected={1}", version, m_version);
698}
699
700/*---------------------------------------------------------------------------*/
701/*---------------------------------------------------------------------------*/
702
703void KeyValueTextReader::Impl::
704_readJSON()
705{
706 // The information about the position in the file and the length of the
707 // JSON text are saved in the epilogue.
708 Int64 file_length = m_reader.fileLength();
709 // Checks the file length as a precaution
710 Int64 struct_size = BasicReaderWriterDatabaseEpilogFormat::STRUCT_SIZE;
711 if (file_length < struct_size)
712 ARCANE_FATAL("File is too short length={0} minimum={1}", file_length, struct_size);
713
715
716 // Reads the epilogue and verifies that the version is supported.
717 {
718 _readDirect(file_length - struct_size, epilog.bytes());
719 const int expected_version = 1;
720 if (epilog.version() != expected_version)
721 ARCANE_FATAL("Bad version for epilog version={0} expected={1}",
722 epilog.version(), expected_version);
723 }
724
725 UniqueArray<std::byte> json_bytes;
726
727 // Reads the JSON data
728 {
729 Int64 file_offset = epilog.jsonDataInfoFileOffset();
730 Int64 meta_data_size = epilog.jsonDataInfoSize();
731 //std::cout << "FILE_INFO: offset=" << file_offset << " meta_data_size=" << meta_data_size << "\n";
732 json_bytes.resize(meta_data_size);
733 _readDirect(file_offset, json_bytes);
734 }
735
736 // Fills the database info from the JSON
737 {
738 JSONDocument json_doc;
739 json_doc.parse(json_bytes);
740 JSONValue root = json_doc.root();
741 JSONValue data = root.child("Data");
742 UniqueArray<Int64> extents;
743 extents.reserve(12);
744 for (JSONValue v : data.valueAsArray()) {
745 String name = v.child("Name").value();
746 Int64 file_offset = v.child("FileOffset").valueAsInt64();
747 //std::cout << "Name=" << name << "\n";
748 //std::cout << "FileOffset=" << file_offset << "\n";
749 JSONValueList extents_info = v.child("Extents").valueAsArray();
750 extents.clear();
751 for (JSONValue v2 : extents_info) {
752 extents.add(v2.valueAsInt64());
753 }
754 Impl::DataInfo x;
755 x.m_file_offset = file_offset;
756 x.m_extents.fill(extents.view());
757 m_data_infos.insert(std::make_pair(name, x));
758 }
759 }
760}
761
762/*---------------------------------------------------------------------------*/
763/*---------------------------------------------------------------------------*/
764
765void KeyValueTextReader::
766getExtents(const String& key_name, SmallSpan<Int64> extents)
767{
768 Integer dimension_array_size = extents.size();
769 if (m_p->m_version >= 3) {
770 Impl::DataInfo& data = m_p->findData(key_name);
771 Impl::ExtentsInfo& exi = data.m_extents;
772 if (extents.size() != exi.size())
773 ARCANE_FATAL("Bad size for extents size={0} expected={1}", extents.size(), exi.size());
774 extents.copy(exi.view());
775 }
776 else {
777 if (m_p->m_version == 1) {
778 // In version 1, dimensions are 'Int32'
780 if (dimension_array_size > 0) {
781 dims.resize(dimension_array_size);
782 m_p->m_reader.read(asWritableBytes(dims));
783 }
784 for (Integer i = 0; i < dimension_array_size; ++i)
785 extents[i] = dims[i];
786 }
787 else {
788 if (dimension_array_size > 0) {
789 m_p->m_reader.read(asWritableBytes(extents));
790 }
791 }
792 }
793}
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
798void KeyValueTextReader::Impl::
799readIntegers(const String& key, Span<Integer> values)
800{
801 _setFileOffset(key);
802 m_reader.readIntegers(values);
803}
804
805/*---------------------------------------------------------------------------*/
806/*---------------------------------------------------------------------------*/
807
808void KeyValueTextReader::Impl::
809read(const String& key, Span<std::byte> values)
810{
811 _setFileOffset(key);
812
813 IDataCompressor* d = m_data_compressor.get();
814 Int64 len = values.size();
815 if (d && len > d->minCompressSize()) {
816 UniqueArray<std::byte> compressed_values;
817 Int64 compressed_size = 0;
818 m_reader.read(asWritableBytes(Span<Int64>(&compressed_size, 1)));
819 compressed_values.resize(compressed_size);
820 _read2(key, compressed_values);
821 m_data_compressor->decompress(compressed_values, values);
822 }
823 else {
824 _read2(key, values);
825 }
826}
827
828/*---------------------------------------------------------------------------*/
829/*---------------------------------------------------------------------------*/
830
831void KeyValueTextReader::Impl::
832_read2(const String& key, Span<std::byte> values)
833{
834 if (m_hash_database.get()) {
835 IHashAlgorithm* hash_algo = m_hash_algorithm.get();
836 if (!hash_algo)
837 ARCANE_FATAL("Can not use hash database without hash algorithm");
838 Int32 hash_size = hash_algo->hashSize();
839 SmallArray<Byte, 1024> hash_as_bytes;
840 hash_as_bytes.resize(hash_size);
841 m_reader.read(asWritableBytes(hash_as_bytes));
842 String hash_value = Convert::toHexaString(hash_as_bytes);
843 info(5) << "READ_KW_HASH key=" << key << " hash=" << hash_value << " expected_len=" << values.size();
844 HashDatabaseReadArgs args(hash_value, values);
845 m_hash_database->readValues(args);
846
847 // Verifies the hash
848 if (arcaneIsCheck()) {
849 Hasher hasher;
850 hasher.setHashAlgorithm(hash_algo);
851 SmallArray<Byte, 1024> hash_result;
852 hasher.computeHash(values, hash_result);
853 String check_hash_value = Convert::toHexaString(hash_result);
854 if (check_hash_value != hash_value)
855 ARCANE_FATAL("Invalid hash expected={0} read={1} key={2}", hash_value, check_hash_value, key);
856 }
857 }
858 else
859 m_reader.read(values);
860}
861
862/*---------------------------------------------------------------------------*/
863/*---------------------------------------------------------------------------*/
864
865void KeyValueTextReader::Impl::
866_setFileOffset(const String& key_name)
867{
868 // With versions prior to version 3, the caller
869 // positions the offset because it is the only one that knows it.
870 if (m_version >= 3) {
871 Impl::DataInfo& data = findData(key_name);
872 m_reader.setFileOffset(data.m_file_offset);
873 }
874}
875
876/*---------------------------------------------------------------------------*/
877/*---------------------------------------------------------------------------*/
878
879/*---------------------------------------------------------------------------*/
880/*---------------------------------------------------------------------------*/
881
882String KeyValueTextReader::
883fileName() const
884{
885 return m_p->m_reader.fileName();
886}
887
888/*---------------------------------------------------------------------------*/
889/*---------------------------------------------------------------------------*/
890
891void KeyValueTextReader::
892setFileOffset(Int64 v)
893{
894 m_p->m_reader.setFileOffset(v);
895}
896
897/*---------------------------------------------------------------------------*/
898/*---------------------------------------------------------------------------*/
899
900void KeyValueTextReader::
901setDataCompressor(Ref<IDataCompressor> ds)
902{
903 m_p->m_data_compressor = ds;
904}
905
906/*---------------------------------------------------------------------------*/
907/*---------------------------------------------------------------------------*/
908
909Ref<IDataCompressor> KeyValueTextReader::
910dataCompressor() const
911{
912 return m_p->m_data_compressor;
913}
914
915/*---------------------------------------------------------------------------*/
916/*---------------------------------------------------------------------------*/
917
918void KeyValueTextReader::
919setHashAlgorithm(Ref<IHashAlgorithm> v)
920{
921 m_p->m_hash_algorithm = v;
922}
923
924/*---------------------------------------------------------------------------*/
925/*---------------------------------------------------------------------------*/
926
927Ref<IHashAlgorithm> KeyValueTextReader::
928hashAlgorithm() const
929{
930 return m_p->m_hash_algorithm;
931}
932
933/*---------------------------------------------------------------------------*/
934/*---------------------------------------------------------------------------*/
935
936void KeyValueTextReader::
937readIntegers(const String& key, Span<Integer> values)
938{
939 m_p->readIntegers(key, values);
940}
941
942/*---------------------------------------------------------------------------*/
943/*---------------------------------------------------------------------------*/
944
945void KeyValueTextReader::
946read(const String& key, Span<std::byte> values)
947{
948 m_p->read(key, values);
949}
950
951/*---------------------------------------------------------------------------*/
952/*---------------------------------------------------------------------------*/
953
954} // End namespace Arcane::impl
955
956/*---------------------------------------------------------------------------*/
957/*---------------------------------------------------------------------------*/
#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_FATAL(...)
Macro throwing a FatalErrorException.
Integer size() const
Number of elements in the vector.
Base class for 1D data vectors.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > view() const
Mutable view of this array.
Interface of a hashing algorithm.
virtual TraceMessage info()=0
Stream for an information message.
void parse(Span< const Byte > bytes)
Reads the file in UTF-8 format.
JSONValue root() const
Root element.
JSONValue child(StringView name) const
Child value with name name. Returns a null value if not found.
View of an array of elements of type T.
Definition Span.h:805
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
View of a UTF-8 character string.
Definition StringView.h:44
constexpr Int64 size() const ARCCORE_NOEXCEPT
Length in bytes of the character string.
Definition StringView.h:99
constexpr Span< const Byte > bytes() const ARCCORE_NOEXCEPT
Returns the conversion of the instance in UTF-8 encoding.
Definition StringView.h:93
bool null() const
Returns true if the string is null.
Definition String.cc:306
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Class to calculate the hash of an array.
Class for writing a text file for backups/restorations.
Definition TextReader2.h:39
Class for writing a text file for backups/restorations.
Definition TextWriter2.h:39
Integer len(const char *s)
Returns the length of the string s.
String toHexaString(ByteConstArrayView input)
Converts a byte array to its hexadecimal representation.
Real getRealTime()
Real time used in seconds.
String getEnvironmentVariable(const String &name)
Environment variable named name.
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
void binaryRead(std::istream &istr, const Span< std::byte > &bytes)
Reads the content of bytes from the stream istr in binary format.
Definition ArrayView.cc:102
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)
Calls the function function and calls std::terminate() if an exception occurs.
double Real
Type representing a real number.
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
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
Impl::SpanTypeFromSize< std::byte, SizeType >::SpanType asWritableBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converts the view into an array of modifiable bytes.
Definition Span.h:1068
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
void binaryWrite(std::ostream &ostr, const Span< const std::byte > &bytes)
Writes the content of bytes to the stream ostr in binary format.
Definition ArrayView.cc:93
std::int32_t Int32
Signed integer type of 32 bits.