Serialbox  2.2.0
Data serialization library and tools for C/C++, Python and Fortran
SerializerImpl.cpp
Go to the documentation of this file.
1 //===-- serialbox/core/SerializerImpl.h ---------------------------------------------*- C++ -*-===//
2 //
3 // S E R I A L B O X
4 //
5 // This file is distributed under terms of BSD license.
6 // See LICENSE.txt for more information
7 //
8 //===------------------------------------------------------------------------------------------===//
9 //
13 //===------------------------------------------------------------------------------------------===//
14 
19 #include "serialbox/core/Type.h"
21 #include "serialbox/core/Version.h"
25 #include <boost/algorithm/string.hpp>
26 #include <fstream>
27 #include <memory>
28 #include <type_traits>
29 
30 #ifdef SERIALBOX_ASYNC_API
31 #include <future>
32 #include <thread>
33 #endif
34 
35 namespace serialbox {
36 
37 int SerializerImpl::enabled_ = 0;
38 
39 SerializerImpl::SerializerImpl(OpenModeKind mode, const std::string& directory,
40  const std::string& prefix, const std::string& archiveName)
41  : mode_(mode), directory_(directory), prefix_(prefix) {
42 
43  if(enabled_ == 0) {
44  const char* envvar = std::getenv("SERIALBOX_SERIALIZATION_DISABLED");
45  enabled_ = (envvar && std::atoi(envvar) > 0) ? -1 : 1;
46  }
47 
48  metaDataFile_ = directory_ / ("MetaData-" + prefix + ".json");
49 
50  savepointVector_ = std::make_shared<SavepointVector>();
51  fieldMap_ = std::make_shared<FieldMap>();
52  globalMetainfo_ = std::make_shared<MetainfoMapImpl>();
53 
54  LOG(info) << "Creating Serializer (mode = " << mode_ << ") from directory " << directory_;
55 
56  // Validate integrity of directory (non-existent directories are created by the archive)
57 
58  try {
59  if(mode_ == OpenModeKind::Read && !filesystem::exists(directory_))
60  // if(mode_ == OpenModeKind::Read && !filesystem::exists(directory_))
61  throw Exception("cannot create Serializer: directory %s does not exist", directory_);
62  } catch(filesystem::filesystem_error& e) {
63  throw Exception("filesystem error: %s", e.what());
64  }
65 
66  // Check if we deal with an older version of serialbox and perform necessary upgrades, otherwise
67  // construct from meta-datafrom JSON
68  if(!upgradeMetaData()) {
70  constructArchive(archiveName);
71  }
72 
73  // If mode is writing drop all files
74  if(mode_ == OpenModeKind::Write)
75  clear();
76 }
77 
78 void SerializerImpl::clear() noexcept {
79  savepointVector_->clear();
80  fieldMap_->clear();
81  globalMetainfo_->clear();
82  archive_->clear();
83 }
84 
85 std::vector<std::string> SerializerImpl::fieldnames() const {
86  std::vector<std::string> fields;
87  fields.reserve(fieldMap_->size());
88  for(auto it = fieldMap_->begin(), end = fieldMap_->end(); it != end; ++it)
89  fields.push_back(it->first);
90  return fields;
91 }
92 
93 static inline bool dimsEqual(const std::vector<int>& dims1, const std::vector<int>& dims2) {
94  if(dims1.size() != dims2.size())
95  return false;
96 
97  // If a dimensions is negative, 0 or 1 it is ignored. We have to do this as gridtools treats empty
98  // dimensions as 0 while STELLA and Frotran usually set them to 1.
99  for(std::size_t i = 0; i < dims1.size(); ++i)
100  if(dims1[i] != dims2[i] && !(dims1[i] <= 1 && dims2[i] <= 1))
101  return false;
102  return true;
103 }
104 
105 std::shared_ptr<FieldMetainfoImpl>
106 SerializerImpl::checkStorageView(const std::string& name, const StorageView& storageView) const {
107 
108  // Check if field exists
109  auto fieldIt = fieldMap_->findField(name);
110  if(fieldIt == fieldMap_->end())
111  throw Exception("field '%s' is not registerd within the Serializer", name);
112 
113  const FieldMetainfoImpl& fieldInfo = *fieldIt->second;
114 
115  // Check if types match
116  if(fieldInfo.type() != storageView.type())
117  throw Exception("field '%s' has type '%s' but was registrered as type '%s'", name,
118  TypeUtil::toString(fieldInfo.type()), TypeUtil::toString(storageView.type()));
119 
120  // Check if dimensions match
121  if(!dimsEqual(fieldInfo.dims(), storageView.dims())) {
122  throw Exception("dimensions of field '%s' do not match regsitered ones:"
123  "\nRegistred as: [ %s ]"
124  "\nGiven as: [ %s ]",
125  name, ArrayUtil::toString(fieldInfo.dims()),
126  ArrayUtil::toString(storageView.dims()));
127  }
128  return fieldIt->second;
129 }
130 
131 //===------------------------------------------------------------------------------------------===//
132 // Writing
133 //===------------------------------------------------------------------------------------------===//
134 
135 void SerializerImpl::write(const std::string& name, const SavepointImpl& savepoint,
136  const StorageView& storageView) {
138  return;
139 
140  LOG(info) << "Serializing field \"" << name << "\" at savepoint \"" << savepoint << "\" ... ";
141 
142  if(mode_ == OpenModeKind::Read)
143  throw Exception("serializer not open in write mode, but write operation requested");
144 
145  //
146  // 1) Check if field is registered within the Serializer and perform some consistency checks
147  //
148  auto info = checkStorageView(name, storageView);
149 
150  //
151  // 2) Locate savepoint and register it if necessary
152  //
153  int savepointIdx = savepointVector_->find(savepoint);
154 
155  if(savepointIdx == -1) {
156  LOG(info) << "Registering new savepoint \"" << savepoint << "\"";
157  savepointIdx = savepointVector_->insert(savepoint);
158  }
159 
160  //
161  // 3) Check if field can be added to Savepoint
162  //
163  if(savepointVector_->hasField(savepointIdx, name))
164  throw Exception("field '%s' already saved at savepoint '%s'", name,
165  (*savepointVector_)[savepointIdx].toString());
166 
167  //
168  // 4) Pass the StorageView to the backend Archive and perform actual data-serialization.
169  //
170  FieldID fieldID = archive_->write(storageView, name, info);
171 
172  //
173  // 5) Register FieldID within Savepoint.
174  //
175  savepointVector_->addField(savepointIdx, fieldID);
176 
177  //
178  // 6) Update meta-data on disk
179  //
180  updateMetaData();
181 
182  LOG(info) << "Successfully serialized field \"" << name << "\"";
183 }
184 
185 //===------------------------------------------------------------------------------------------===//
186 // Reading
187 //===------------------------------------------------------------------------------------------===//
188 
189 void SerializerImpl::read(const std::string& name, const SavepointImpl& savepoint,
190  StorageView& storageView, bool alsoPrevious) {
192  return;
193 
194  LOG(info) << "Deserializing field \"" << name << "\" at savepoint \"" << savepoint << "\" ... ";
195 
196  //
197  // 1) Check if field is registred within the Serializer and perform some consistency checks
198  //
199  auto info = checkStorageView(name, storageView);
200 
201  //
202  // 2) Check if savepoint exists and obtain fieldID
203  //
204  int savepointIdx = savepointVector_->find(savepoint);
205 
206  if(savepointIdx == -1)
207  throw Exception("savepoint '%s' does not exist", savepoint.toString());
208 
209  FieldID fieldID;
210  while (savepointIdx >= 0)
211  {
212  if (savepointVector_->hasField(savepointIdx, name) || !alsoPrevious)
213  {
214  fieldID = savepointVector_->getFieldID(savepointIdx, name);
215  break;
216  }
217  else
218  {
219  // If alsoPrevious is speicifed AND the field was not found,
220  // keep searching backwards
221  --savepointIdx;
222  }
223  }
224 
225  if(savepointIdx == -1)
226  throw Exception("field '%s' not found at or before savepoint '%s'", name, savepoint.toString());
227 
228  //
229  // 3) Pass the StorageView to the backend Archive and perform actual data-deserialization.
230  //
231  archive_->read(storageView, fieldID, info);
232 
233  LOG(info) << "Successfully deserialized field \"" << name << "\"";
234 }
235 
236 void SerializerImpl::readSliced(const std::string& name, const SavepointImpl& savepoint,
237  StorageView& storageView, Slice slice) {
238  if(!archive_->isSlicedReadingSupported())
239  throw Exception("archive '%s' does not support sliced reading", archive_->name());
240 
241  storageView.setSlice(slice);
242  this->read(name, savepoint, storageView);
243 }
244 
245 // This is the global task vector. If we would put the tasks inside SerializerImpl, we would have a
246 // conditional member in a class (i.e depending on a macro) which can cause trouble if someone
247 // compiled the library with SERIALBOX_ASYNC_API but doesn't use it when linking the library which
248 // will smash the stack!
249 #ifdef SERIALBOX_ASYNC_API
250 namespace global {
251 static std::vector<std::future<void>> tasks;
252 }
253 #endif
254 
255 void SerializerImpl::readAsyncImpl(const std::string name, const SavepointImpl savepoint,
256  StorageView storageView) {
257  this->read(name, savepoint, storageView);
258 }
259 
260 void SerializerImpl::readAsync(const std::string& name, const SavepointImpl& savepoint,
261  StorageView& storageView) {
262 #ifdef SERIALBOX_ASYNC_API
263  if(!archive_->isReadingThreadSafe())
264  this->read(name, savepoint, storageView);
265  else
266  // Bad things can happen if we forward the refrences and directly call the SerializerImpl::read,
267  // we thus just make a copy of the arguments.
268  global::tasks.emplace_back(std::async(std::launch::async, &SerializerImpl::readAsyncImpl, this,
269  name, savepoint, storageView));
270 #else
271  this->read(name, savepoint, storageView);
272 #endif
273 }
274 
276 #ifdef SERIALBOX_ASYNC_API
277  try {
278  for(auto& task : global::tasks)
279  task.get();
280  } catch(std::exception& e) {
281  global::tasks.clear();
282  throw Exception(e.what());
283  }
284  global::tasks.clear();
285 #endif
286 }
287 
288 //===------------------------------------------------------------------------------------------===//
289 // JSON Serialization
290 //===------------------------------------------------------------------------------------------===//
291 
293  LOG(info) << "Constructing Serializer from MetaData ... ";
294 
295  // Try open meta-data file
296  if(!filesystem::exists(metaDataFile_)) {
297  if(mode_ != OpenModeKind::Read)
298  return;
299  else
300  throw Exception("cannot create Serializer: MetaData-%s.json not found in %s", prefix_,
301  directory_);
302  }
303 
304  json::json jsonNode;
305  try {
306  std::ifstream fs(metaDataFile_.string(), std::ios::in);
307  fs >> jsonNode;
308  fs.close();
309  } catch(std::exception& e) {
310  throw Exception("JSON parser error: %s", e.what());
311  }
312 
313  try {
314  // Check consistency
315  if(!jsonNode.count("serialbox_version"))
316  throw Exception("node 'serialbox_version' not found");
317 
318  int serialboxVersion = jsonNode["serialbox_version"];
319 
320  if(!Version::isCompatible(serialboxVersion))
321  throw Exception(
322  "serialbox version of MetaData (%s) does not match the version of the library (%s)",
323  Version::toString(serialboxVersion), SERIALBOX_VERSION_STRING);
324 
325  // Check if prefix match
326  if(!jsonNode.count("prefix"))
327  throw Exception("node 'prefix' not found");
328 
329  if(jsonNode["prefix"] != prefix_)
330  throw Exception("inconsistent prefixes: expected '%s' got '%s'", jsonNode["prefix"], prefix_);
331 
332  // Construct globalMetainfo
333  if(jsonNode.count("global_meta_info"))
334  globalMetainfo_->fromJSON(jsonNode["global_meta_info"]);
335 
336  // Construct Savepoints
337  if(jsonNode.count("savepoint_vector"))
338  savepointVector_->fromJSON(jsonNode["savepoint_vector"]);
339 
340  // Construct FieldMap
341  if(jsonNode.count("field_map"))
342  fieldMap_->fromJSON(jsonNode["field_map"]);
343 
344  } catch(Exception& e) {
345  throw Exception("error while parsing %s: %s", metaDataFile_, e.what());
346  }
347 }
348 
349 std::string SerializerImpl::toString() const {
350  std::stringstream ss;
351  ss << "mode = " << mode_ << "\n";
352  ss << "directory = " << directory_ << "\n";
353  ss << "prefix = \"" << prefix_ << "\"\n";
354  ss << "archive = \"" << archive_->name() << "\"\n";
355  ss << "metainfo = " << *globalMetainfo_ << "\n";
356  ss << "savepoints = [";
357  for(const auto& sp : savepointVector_->savepoints())
358  ss << "\n " << *sp;
359  ss << (savepointVector_->savepoints().empty() ? "" : "\n") << "]\n";
360  ss << "fieldmetainfo = [";
361  for(auto it = fieldMap_->begin(), end = fieldMap_->end(); it != end; ++it)
362  ss << "\n " << it->first << ": " << *it->second;
363  ss << (fieldMap_->empty() ? "" : "\n") << "]";
364  return ss.str();
365 }
366 
367 std::ostream& operator<<(std::ostream& stream, const SerializerImpl& s) {
368  return (stream << s.toString());
369 }
370 
371 json::json SerializerImpl::toJSON() const {
372  LOG(info) << "Converting Serializer MetaData to JSON";
373 
374  json::json jsonNode;
375 
376  // Tag version
377  jsonNode["serialbox_version"] =
378  100 * SERIALBOX_VERSION_MAJOR + 10 * SERIALBOX_VERSION_MINOR + SERIALBOX_VERSION_PATCH;
379 
380  // Serialize prefix
381  jsonNode["prefix"] = prefix_;
382 
383  // Serialize globalMetainfo
384  jsonNode["global_meta_info"] = globalMetainfo_->toJSON();
385 
386  // Serialize SavepointVector
387  jsonNode["savepoint_vector"] = savepointVector_->toJSON();
388 
389  // Serialize FieldMap
390  jsonNode["field_map"] = fieldMap_->toJSON();
391 
392  return jsonNode;
393 }
394 
396  LOG(info) << "Update MetaData of Serializer";
397 
398  json::json jsonNode = toJSON();
399 
400  // Write metaData to disk (just overwrite the file, we assume that there is never more than one
401  // Serializer per data set and thus our in-memory copy is always the up-to-date one)
402  std::ofstream fs(metaDataFile_.string(), std::ios::out | std::ios::trunc);
403  if(!fs.is_open())
404  throw Exception("cannot open file: %s", metaDataFile_);
405  fs << jsonNode.dump(1) << std::endl;
406  fs.close();
407 
408  // Update archive meta-data
409  archive_->updateMetaData();
410 }
411 
413  archive_ = ArchiveFactory::create(archiveName, mode_, directory_.string(), prefix_);
414 }
415 
416 //===------------------------------------------------------------------------------------------===//
417 // Upgrade
418 //===------------------------------------------------------------------------------------------===//
419 
421  filesystem::path oldMetaDataFile = directory_ / (prefix_ + ".json");
422 
423  //
424  // Check if upgrade is necessary
425  //
426 
427  try {
428  // Check if prefix.json exists
429  if(!filesystem::exists(oldMetaDataFile))
430  return false;
431 
432  LOG(info) << "Detected old serialbox meta-data " << oldMetaDataFile;
433 
434  // Check if we already upgraded this archive
435  if(filesystem::exists(metaDataFile_) && (filesystem::last_write_time(oldMetaDataFile) <
436  filesystem::last_write_time(metaDataFile_))) {
437  return false;
438  }
439  } catch(filesystem::filesystem_error& e) {
440  throw Exception("filesystem error: %s", e.what());
441  }
442 
443  LOG(info) << "Upgrading meta-data to serialbox version (" << SERIALBOX_VERSION_STRING << ") ...";
444 
445  if(mode_ != OpenModeKind::Read)
446  throw Exception("old serialbox archives cannot be opened in 'Write' or 'Append' mode");
447 
448  json::json oldJson;
449  std::ifstream ifs(oldMetaDataFile.string());
450  if(!ifs.is_open())
451  throw Exception("upgrade failed: cannot open %s", oldMetaDataFile);
452  ifs >> oldJson;
453  ifs.close();
454 
455  //
456  // Upgrade Metainfo
457  //
458 
459  // Try to guess the precision of the floating point type. We try to match the floating point type
460  // of the fields while defaulting to double.
461  TypeID globalMetainfoFloatType = TypeID::Float64;
462  if(oldJson.count("FieldsTable") && oldJson["FieldsTable"].size() > 0) {
463  if(oldJson["FieldsTable"][0]["__elementtype"] == "float")
464  globalMetainfoFloatType = TypeID::Float32;
465  }
466 
467  LOG(info) << "Deduced float type of global meta-info as: " << globalMetainfoFloatType;
468 
469  if(oldJson.count("GlobalMetainfo")) {
470 
471  LOG(info) << "Upgrading global meta-info ...";
472 
473  for(auto it = oldJson["GlobalMetainfo"].begin(), end = oldJson["GlobalMetainfo"].end();
474  it != end; ++it) {
475 
476  LOG(info) << "Inserting global meta-info: key = " << it.key() << ", value = " << it.value();
477 
478  std::string key = it.key();
479  if(!boost::algorithm::starts_with(key, "__")) {
480  if(it.value().is_string()) {
481  std::string value = it.value();
482  addGlobalMetainfo(key, value);
483  } else if(it.value().is_boolean()) {
484  addGlobalMetainfo(key, bool(it.value()));
485  } else if(it.value().is_number_integer()) {
486  addGlobalMetainfo(key, int(it.value()));
487  } else if(it.value().is_number_float()) {
488  if(globalMetainfoFloatType == TypeID::Float32)
489  addGlobalMetainfo(key, float(it.value()));
490  else
491  addGlobalMetainfo(key, double(it.value()));
492  } else
493  throw Exception("failed to upgrade: cannot deduce type of globalMetainfo '%s'", it.key());
494  }
495  }
496 
497  LOG(info) << "Successfully upgraded global meta-info";
498  }
499 
500  //
501  // Upgrade FieldsTable
502  //
503 
504  if(oldJson.count("FieldsTable")) {
505 
506  LOG(info) << "Upgrading fields table ...";
507 
508  const auto& fieldsTable = oldJson["FieldsTable"];
509  for(std::size_t i = 0; i < fieldsTable.size(); ++i) {
510  auto& fieldInfo = fieldsTable[i];
511  std::string name = fieldInfo["__name"];
512 
513  LOG(info) << "Inserting field: " << name;
514 
515  // Get Type
516  std::string elementtype = fieldInfo["__elementtype"];
517  TypeID type = TypeID::Float64;
518 
519  if(elementtype == "int")
520  type = TypeID::Int32;
521  else if(elementtype == "float")
522  type = TypeID::Float32;
523  else if(elementtype == "double")
524  type = TypeID::Float64;
525 
526  // Get dimension
527  std::vector<int> dims(3, 1);
528  dims[0] = int(fieldInfo["__isize"]);
529  dims[1] = int(fieldInfo["__jsize"]);
530  dims[2] = int(fieldInfo["__ksize"]);
531 
532  if(fieldInfo.count("__lsize"))
533  dims.push_back(int(fieldInfo["__lsize"]));
534 
535  // Iterate field meta-info
536  MetainfoMapImpl metaInfo;
537  for(auto it = fieldInfo.begin(), end = fieldInfo.end(); it != end; ++it) {
538  std::string key = it.key();
539  if(it.value().is_string()) {
540  std::string value = it.value();
541  metaInfo.insert(key, value);
542  } else if(it.value().is_boolean()) {
543  metaInfo.insert(key, bool(it.value()));
544  } else if(it.value().is_number_integer()) {
545  metaInfo.insert(key, int(it.value()));
546  } else if(it.value().is_number_float()) {
547  if(globalMetainfoFloatType == TypeID::Float32)
548  metaInfo.insert(key, float(it.value()));
549  else
550  metaInfo.insert(key, double(it.value()));
551  } else
552  throw Exception("failed to upgrade: Cannot deduce type of meta-info '%s' of field '%s'",
553  key, name);
554  }
555 
556  fieldMap_->insert(name, type, dims, metaInfo);
557  }
558 
559  LOG(info) << "Successfully upgraded fields table";
560  }
561 
562  //
563  // Upgrade SavepointVector and ArchiveMetaData
564  //
565 
566  // Construct archive but don't parse the meta-data (we will do it ourselves below)
567  archive_ = std::make_unique<BinaryArchive>(mode_, directory_.string(), prefix_, true);
568 
569  // Old serialbox always uses SHA256
570  static_cast<BinaryArchive*>(archive_.get())->setHash(HashFactory::create("SHA256"));
571 
572  BinaryArchive::FieldTable& fieldTable = static_cast<BinaryArchive*>(archive_.get())->fieldTable();
573 
574  if(oldJson.count("OffsetTable")) {
575 
576  LOG(info) << "Upgrading offset table ...";
577 
578  const auto& offsetTable = oldJson["OffsetTable"];
579  for(std::size_t i = 0; i < offsetTable.size(); ++i) {
580  auto& offsetTableEntry = offsetTable[i];
581 
582  // Create savepoint
583  std::string name = offsetTableEntry["__name"];
584  SavepointImpl savepoint(name);
585 
586  // Add meta-info to savepoint
587  for(auto it = offsetTableEntry.begin(), end = offsetTableEntry.end(); it != end; ++it) {
588  std::string key = it.key();
589  if(!boost::algorithm::starts_with(key, "__")) {
590  if(it.value().is_string()) {
591  std::string value = it.value();
592  savepoint.addMetainfo(it.key(), value);
593  } else if(it.value().is_boolean()) {
594  savepoint.addMetainfo(it.key(), bool(it.value()));
595  } else if(it.value().is_number_integer()) {
596  savepoint.addMetainfo(it.key(), int(it.value()));
597  } else if(it.value().is_number_float()) {
598  if(globalMetainfoFloatType == TypeID::Float32)
599  savepoint.addMetainfo(it.key(), float(it.value()));
600  else
601  savepoint.addMetainfo(it.key(), double(it.value()));
602  } else
603  throw Exception(
604  "failed to upgrade: Cannot deduce type of meta-info '%s' of savepoint '%s'",
605  it.key(), name);
606  }
607  }
608 
609  LOG(info) << "Adding savepoint: " << savepoint;
610 
611  // Register savepoint
612  int savepointIdx = savepointVector_->insert(savepoint);
613  assert(savepointIdx != -1);
614 
615  // Add fields to savepoint and field table of the archive
616  for(auto it = offsetTableEntry["__offsets"].begin(),
617  end = offsetTableEntry["__offsets"].end();
618  it != end; ++it) {
619  std::string fieldname = it.key();
620 
621  FieldID fieldID{fieldname, 0};
622  BinaryArchive::FileOffsetType fileOffset{it.value()[0], it.value()[1]};
623 
624  // Insert offsets into the field table (This mimics the write operation of the
625  // Binary archive)
626  auto fieldTableIt = fieldTable.find(fieldname);
627  if(fieldTableIt != fieldTable.end()) {
628  BinaryArchive::FieldOffsetTable& fieldOffsetTable = fieldTableIt->second;
629  bool fieldAlreadySerialized = false;
630 
631  // Check if field has already been serialized by comparing the checksum
632  for(std::size_t i = 0; i < fieldOffsetTable.size(); ++i)
633  if(fileOffset.checksum == fieldOffsetTable[i].checksum) {
634  fieldAlreadySerialized = true;
635  fieldID.id = i;
636  break;
637  }
638 
639  // Append field at the end
640  if(!fieldAlreadySerialized) {
641  assert(fileOffset.offset != 0);
642  fieldID.id = fieldOffsetTable.size();
643  fieldOffsetTable.push_back(fileOffset);
644  }
645  } else {
646  assert(fileOffset.offset == 0);
647  fieldID.id = 0;
648  fieldTable.insert(BinaryArchive::FieldTable::value_type(
649  fieldname, BinaryArchive::FieldOffsetTable(1, fileOffset)));
650  }
651 
652  // Add field to savepoint
653  savepointVector_->addField(savepointIdx, fieldID);
654 
655  LOG(info) << "Adding field '" << fieldID << "' to savepoint " << savepoint;
656  }
657  }
658 
659  LOG(info) << "Successfully upgraded offset table";
660  }
661 
662  // Try to write the mata data to disk so that we can avoid such an upgrade in the future. However,
663  // if we read from a location where we have no write permission, this should be non-fatal.
664  try {
665  updateMetaData();
666  } catch(Exception& e) {
667  LOG(warning) << "Failed to write upgraded meta-data to disk: " << e.what();
668  }
669 
670  LOG(info) << "Successfully upgraded MetaData to serialbox version (" << SERIALBOX_VERSION_STRING
671  << ")";
672 
673  return true;
674 }
675 
676 } // namespace serialbox
static std::string toString(const Array< T > &array)
Convert to string.
Definition: Array.h:38
void readAsync(const std::string &name, const SavepointImpl &savepoint, StorageView &storageView)
Asynchronously deserialize field name (given as storageView) at savepoint from disk using std::async...
static std::string toString(int version)
Convert to string.
Definition: Version.h:38
bool insert(KeyType &&key, ValueType &&value) noexcept
Insert a new element in the map.
void constructArchive(const std::string &archiveName)
Construct Archive from JSON.
Meta-information of a data field.
void updateMetaData()
Convert meta-data to JSON and serialize to MetaData-prefix.json and ArchiveMetaData-prefix.json.
static int serializationStatus() noexcept
Get the status of serialization.
void readAsyncImpl(const std::string name, const SavepointImpl savepoint, StorageView storageView)
Implementation of SerializerImpl::readAsync.
std::vector< FileOffsetType > FieldOffsetTable
Table of ids and corresponding offsets whithin in each field (i.e file)
Definition: BinaryArchive.h:47
void addGlobalMetainfo(StringType &&key, ValueType &&value)
Add a new key-value pair to the global meta-information of the Serializer.
#define LOG(severity)
Logging infrastructure.
Definition: Logging.h:102
friend std::ostream & operator<<(std::ostream &stream, const SerializerImpl &s)
Convert to stream.
Represent a mutable view to a multi-dimensional storage.
Definition: StorageView.h:33
static std::unique_ptr< Hash > create(const std::string &name)
Construct an instance of the Hash name
Definition: HashFactory.cpp:26
void setSlice(Slice slice)
Set the slice of the StorageView
Definition: StorageView.cpp:71
TypeID type() const noexcept
Get type.
Definition: StorageView.h:90
void addMetainfo(StringType &&key, ValueType &&value)
Add a new key = value pair to the metaInfo of the Savepoint.
Definition: SavepointImpl.h:74
Namespace of the serialbox library.
Definition: Archive.h:25
TypeID
Type-id of types recognized by serialbox.
Definition: Type.h:55
std::string toString() const
Convert to string.
std::shared_ptr< FieldMetainfoImpl > checkStorageView(const std::string &name, const StorageView &storageView) const
Check if storageView is consistent with the field name
TypeID & type() noexcept
Access TypeID.
bool upgradeMetaData()
Check if the current directory contains meta-information of an older version of serialbox and upgrade...
Shared implementation of the Serializer.
Uniquely identifiy a field.
Definition: FieldID.h:27
static std::unique_ptr< Archive > create(const std::string &name, OpenModeKind mode, const std::string &directory, const std::string &prefix)
Construct an instance of the archive ´name´
const std::vector< int > & dims() const noexcept
Get dimensions.
Definition: StorageView.h:96
serialbox::Exception exception
Exception class which stores a human-readable error description.
Definition: Exception.h:33
std::vector< std::string > fieldnames() const
Get a vector of all registered fields.
Hash-map of meta-information of the form key = value pair or key = {value1, ..., valueN} ...
static std::string toString(TypeID id)
Convert to string.
Definition: Type.cpp:35
void constructMetaDataFromJson()
Construct meta-data from JSON.
std::unordered_map< std::string, FieldOffsetTable > FieldTable
Table of all fields owned by this archive, each field has a corresponding file.
Definition: BinaryArchive.h:50
void write(const std::string &name, const SavepointImpl &savepoint, const StorageView &storageView)
Serialize field name (given as storageView) at savepoint to disk.
Non-portable binary archive.
Definition: BinaryArchive.h:32
OpenModeKind
Policy for opening files in the Serializer and Archive.
Definition: Type.h:40
static bool isCompatible(int version) noexcept
Check if the given version is compatible with the current library version (i.e. is older) ...
Definition: Version.h:61
serialbox::Slice slice
Specification of the slice indices which is used for partial loading of serialized data...
Definition: Slice.h:43
json::json toJSON() const
Convert all members of the Serializer to JSON.
void readSliced(const std::string &name, const SavepointImpl &savepoint, StorageView &storageView, Slice slice)
Deserialize sliced field name (given as storageView and slice) at savepoint from disk.
std::string archiveName() const noexcept
Name of the archive in use.
Specification of the slice indices which is used for partial loading of serialized data...
Definition: Slice.h:53
Exception class which stores a human-readable error description.
Definition: Exception.h:30
void clear() noexcept
Drop all field and savepoint meta-data.
SerializerImpl(const SerializerImpl &)=delete
Copy constructor [deleted].
Shared implementation of the Savepoint.
Definition: SavepointImpl.h:38
std::vector< int > & dims() noexcept
Access dimensions.
void read(const std::string &name, const SavepointImpl &savepoint, StorageView &storageView, bool alsoPrevious=false)
Deserialize field name (given as storageView) at savepoint from disk.
void waitForAll()
Wait for all pending asynchronous read operations and reset the internal queue.