14#include "arcane/std/internal/BasicReaderWriterDatabase.h"
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"
28#include "arcane/ArcaneException.h"
30#include "arcane/std/internal/TextReader2.h"
31#include "arcane/std/internal/TextWriter2.h"
32#include "arcane/std/internal/IHashDatabase.h"
55 Real t1 = platform::getRealTime();
56 m_nb_processed_bytes += bytes.size();
58 Real
t2 = platform::getRealTime();
59 m_hash_time += (
t2 - t1);
65 m_hash_algorithm =
algo;
70 if (m_nb_processed_bytes == 0)
72 Real
nb_byte_per_second =
static_cast<Real
>(m_nb_processed_bytes) / (m_hash_time + 1.0e-9);
75 tm->
info() <<
"Hasher:nb_processed=" << m_nb_processed_bytes
76 <<
" hash_time=" << m_hash_time
84 Int64 m_nb_processed_bytes = 0;
85 Real m_hash_time = 0.0;
99 static constexpr Int64 STRUCT_SIZE = 128;
105 checkStructureSize();
106 for (
int i = 0; i < 10; ++i)
107 m_remaining_padding[i] = i;
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; }
122 return {
reinterpret_cast<std::byte*
>(
this), STRUCT_SIZE };
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];
140 static void checkStructureSize()
143 if (s != STRUCT_SIZE)
144 ARCANE_FATAL(
"Invalid size for epilog format size={0} expected={1}", s, STRUCT_SIZE);
159 static constexpr Int64 STRUCT_SIZE = 128;
165 checkStructureSize();
166 for (
int i = 0; i < 12; ++i)
167 m_remaining_padding[i] = i;
174 return {
reinterpret_cast<std::byte*
>(
this), STRUCT_SIZE };
176 void setVersion(Int32 version) { m_version = version; }
177 Int32 version()
const {
return m_version; }
181 if (m_header_begin[0] !=
'A' || m_header_begin[1] !=
'C' || m_header_begin[2] !=
'R' || m_header_begin[3] != (
Byte)39)
190 std::array<Byte, 4> m_header_begin = {
'A',
'C',
'R', 39 };
192 Int32 m_endian_int = 0x01020304;
195 Int32 m_padding0 = 0;
196 Int64 m_padding1 = 0;
197 Int64 m_padding2 = 0;
198 Int64 m_remaining_padding[12];
202 static void checkStructureSize()
205 if (s != STRUCT_SIZE)
206 ARCANE_FATAL(
"Invalid size for header format size={0} expected={1}", s, STRUCT_SIZE);
220 static constexpr int MAX_SIZE = 8;
228 for (Int32 i = 0; i < nb; ++i)
235 return m_large_extents.
view();
237 Int32 size()
const {
return nb; }
245 Int64 sizes[MAX_SIZE];
251 Int64 m_file_offset = 0;
278 DataInfo& findData(
const String& key_name)
280 auto x = m_data_infos.find(key_name);
281 if (x == m_data_infos.end())
282 ARCANE_FATAL(
"Can not find key '{0}' in database", key_name);
288 std::map<String, DataInfo> m_data_infos;
289 Ref<IDataCompressor> m_data_compressor;
290 Ref<IHashAlgorithm> m_hash_algorithm;
291 Ref<IHashDatabase> m_hash_database;
323 Int64 fileOffset() {
return m_writer.fileOffset(); }
330 void _writeKey(
const String& key);
382 header.setVersion(m_version);
383 binaryWrite(m_writer.stream(),
header.bytes());
389void KeyValueTextWriter::Impl::
396 jsw.writeKey(
"Data");
398 for (
auto& x : m_data_infos) {
400 jsw.write(
"Name", x.first);
401 jsw.write(
"FileOffset", x.second.m_file_offset);
402 jsw.write(
"Extents", x.second.m_extents.view());
407 std::ostream& stream = m_writer.stream();
415 binaryWrite(stream, asBytes(buf.
bytes()));
421 binaryWrite(stream,
epilog.bytes());
428void KeyValueTextWriter::Impl::
429setExtents(
const String& key_name, SmallSpan<const Int64> extents)
431 if (m_version >= 3) {
432 _addKey(key_name, 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) {
445 UniqueArray<Integer> dims(dimension_array_size);
446 for (Integer i = 0; i < dimension_array_size; ++i)
452 m_writer.write(
asBytes(extents));
460void KeyValueTextWriter::Impl::
461write(
const String& key, Span<const std::byte> values)
465 IDataCompressor* d = m_data_compressor.get();
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);
475 _write2(key, values);
481void KeyValueTextWriter::Impl::
482_write2(
const String& key, Span<const std::byte> values)
484 if (m_hash_database.get()) {
485 IHashAlgorithm* hash_algo = m_hash_algorithm.get();
487 ARCANE_FATAL(
"Can not use hash database without hash algorithm");
489 SmallArray<Byte, 1024> hash_result;
490 m_hasher.computeHash(values, hash_result);
493 HashDatabaseWriteResult result;
494 HashDatabaseWriteArgs args(values, hash_value);
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));
502 m_writer.write(values);
508String KeyValueTextWriter::
511 return m_p->m_writer.fileName();
517void KeyValueTextWriter::
518setDataCompressor(Ref<IDataCompressor> ds)
520 m_p->m_data_compressor = ds;
526Ref<IDataCompressor> KeyValueTextWriter::
527dataCompressor()
const
529 return m_p->m_data_compressor;
535void KeyValueTextWriter::
536setHashAlgorithm(Ref<IHashAlgorithm> v)
538 m_p->m_hash_algorithm = v;
539 m_p->m_hasher.setHashAlgorithm(v.get());
545Ref<IHashAlgorithm> KeyValueTextWriter::
548 return m_p->m_hash_algorithm;
554Int64 KeyValueTextWriter::
557 return m_p->m_writer.fileOffset();
563void KeyValueTextWriter::Impl::
564_addKey(
const String& key, SmallSpan<const Int64> extents)
566 Impl::DataInfo d{ -1, Impl::ExtentsInfo() };
567 d.m_extents.fill(extents);
568 m_data_infos.insert(std::make_pair(key, d));
574void KeyValueTextWriter::Impl::
575_writeKey(
const String& key)
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();
591void KeyValueTextWriter::
592setExtents(
const String& key_name, SmallSpan<const Int64> extents)
594 m_p->setExtents(key_name, extents);
600void KeyValueTextWriter::
601write(
const String& key, Span<const std::byte> values)
603 m_p->write(key, values);
622 if (m_version >= 3) {
669void KeyValueTextReader::Impl::
672 m_reader.setFileOffset(offset);
673 std::istream& s = m_reader.stream();
674 binaryRead(s, bytes);
676 ARCANE_FATAL(
"Can not read file part offset={0} length={1}", offset, bytes.length());
692 _readDirect(0, bytes);
694 Int32 version =
header.version();
695 if (version != m_version)
696 ARCANE_FATAL(
"Invalid version for ACR file version={0} expected={1}", version, m_version);
702void KeyValueTextReader::Impl::
709 Int64
struct_size = BasicReaderWriterDatabaseEpilogFormat::STRUCT_SIZE;
720 ARCANE_FATAL(
"Bad version for epilog version={0} expected={1}",
743 for (
JSONValue v : data.valueAsArray()) {
744 String name = v.child(
"Name").value();
745 Int64
file_offset = v.child(
"FileOffset").valueAsInt64();
751 extents.add(v2.valueAsInt64());
754 x.m_file_offset = file_offset;
755 x.m_extents.fill(extents.view());
756 m_data_infos.insert(std::make_pair(name, x));
764void KeyValueTextReader::
765getExtents(
const String& key_name, SmallSpan<Int64> extents)
767 Integer dimension_array_size = extents.size();
768 if (m_p->m_version >= 3) {
769 Impl::DataInfo& data = m_p->findData(key_name);
770 Impl::ExtentsInfo& exi = data.m_extents;
771 if (extents.size() != exi.size())
772 ARCANE_FATAL(
"Bad size for extents size={0} expected={1}", extents.size(), exi.size());
773 extents.copy(exi.view());
776 if (m_p->m_version == 1) {
779 if (dimension_array_size > 0) {
780 dims.
resize(dimension_array_size);
783 for (Integer i = 0; i < dimension_array_size; ++i)
784 extents[i] = dims[i];
787 if (dimension_array_size > 0) {
797void KeyValueTextReader::Impl::
798readIntegers(
const String& key, Span<Integer> values)
801 m_reader.readIntegers(values);
807void KeyValueTextReader::Impl::
808read(
const String& key, Span<std::byte> values)
812 IDataCompressor* d = m_data_compressor.get();
814 if (d && len > d->minCompressSize()) {
815 UniqueArray<std::byte> compressed_values;
816 Int64 compressed_size = 0;
818 compressed_values.resize(compressed_size);
819 _read2(key, compressed_values);
820 m_data_compressor->decompress(compressed_values, values);
830void KeyValueTextReader::Impl::
831_read2(
const String& key, Span<std::byte> values)
833 if (m_hash_database.get()) {
834 IHashAlgorithm* hash_algo = m_hash_algorithm.get();
836 ARCANE_FATAL(
"Can not use hash database without hash algorithm");
837 Int32 hash_size = hash_algo->hashSize();
838 SmallArray<Byte, 1024> hash_as_bytes;
839 hash_as_bytes.resize(hash_size);
842 info(5) <<
"READ_KW_HASH key=" << key <<
" hash=" << hash_value <<
" expected_len=" << values.size();
843 HashDatabaseReadArgs args(hash_value, values);
844 m_hash_database->readValues(args);
847 m_reader.read(values);
853void KeyValueTextReader::Impl::
854_setFileOffset(
const String& key_name)
858 if (m_version >= 3) {
859 Impl::DataInfo& data = findData(key_name);
860 m_reader.setFileOffset(data.m_file_offset);
870String KeyValueTextReader::
873 return m_p->m_reader.fileName();
879void KeyValueTextReader::
880setFileOffset(
Int64 v)
882 m_p->m_reader.setFileOffset(v);
888void KeyValueTextReader::
889setDataCompressor(Ref<IDataCompressor> ds)
891 m_p->m_data_compressor = ds;
897Ref<IDataCompressor> KeyValueTextReader::
898dataCompressor()
const
900 return m_p->m_data_compressor;
906void KeyValueTextReader::
907setHashAlgorithm(Ref<IHashAlgorithm> v)
909 m_p->m_hash_algorithm = v;
915Ref<IHashAlgorithm> KeyValueTextReader::
918 return m_p->m_hash_algorithm;
924void KeyValueTextReader::
925readIntegers(
const String& key, Span<Integer> values)
927 m_p->readIntegers(key, values);
933void KeyValueTextReader::
934read(
const String& key, Span<std::byte> values)
936 m_p->read(key, values);
#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_FATAL(...)
Macro envoyant une exception FatalErrorException.
Interface d'un algorithme de hashage.
virtual void computeHash64(Span< const Byte > input, ByteArray &output)
Calcule la valeur du hash pour le tableau input.
Gestion d'un document JSON.
Liste de valeurs d'un document JSON.
Représente une valeur JSON.
JSONValue child(StringView name) const
Valeur fille de nom name. Retourne une valeur nulle si non trouvé.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Classe pour calculer le hash d'un tableau.
void _readHeader()
En-tête du format de fichier.
void _writeHeader()
En-tête du format de fichier.
Classe d'écriture d'un fichier texte pour les protections/reprises.
Classe d'écriture d'un fichier texte pour les protections/reprises.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
ArrayView< T > view() const
Vue mutable sur ce tableau.
Vue constante d'un tableau de type T.
Interface du gestionnaire de traces.
Vue sur une chaîne de caractères UTF-8.
constexpr Span< const Byte > bytes() const ARCCORE_NOEXCEPT
Retourne la conversion de l'instance dans l'encodage UTF-8.
constexpr Int64 size() const ARCCORE_NOEXCEPT
Longueur en octet de la chaîne de caractères.
Chaîne de caractères unicode.
Classe d'accès aux traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
Integer len(const char *s)
Retourne la longueur de la chaîne s.
Integer toInteger(Real r)
Converti un Int64 en un Integer.
String toHexaString(ByteConstArrayView input)
Converti un tableau d'octet en sa représentation hexadécimale.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Int32 Integer
Type représentant un entier.
detail::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets non modifiables.
detail::SpanTypeFromSize< std::byte, SizeType >::SpanType asWritableBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets modifiables.
std::int32_t Int32
Type entier signé sur 32 bits.