Serialbox  2.2.0
Data serialization library and tools for C/C++, Python and Fortran
Serializer.cpp
Go to the documentation of this file.
1 //===-- serialbox/core/frontend/stella/Serializer.cpp -------------------------------*- 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 <boost/make_shared.hpp>
20 #include <cstdlib>
21 
22 namespace serialbox {
23 
24 namespace stella {
25 
26 int Serializer::enabled_ = 0;
27 
28 Serializer::Serializer() { serializerImpl_ = nullptr; }
29 
31  switch(serializerImpl_->mode()) {
32  case OpenModeKind::Read:
33  return SerializerOpenModeRead;
34  case OpenModeKind::Write:
35  return SerializerOpenModeWrite;
36  case OpenModeKind::Append:
37  return SerializerOpenModeAppend;
38  default:
39  serialbox_unreachable("invalid mode");
40  }
41 }
42 
44 
46 
47 std::string Serializer::directory() const { return serializerImpl_->directory().string(); }
48 
49 std::string Serializer::prefix() const { return serializerImpl_->prefix(); }
50 
51 void Serializer::Init(const std::string& directory, const std::string& prefix,
54  const char* envvar = std::getenv("STELLA_SERIALIZATION_DISABLED");
55  if(envvar && std::atoi(envvar) > 0)
57  }
58 
59  // Initialize SerializerImpl
60  try {
61  switch(mode) {
62  case SerializerOpenModeRead:
63  serializerImpl_ =
64  boost::make_shared<SerializerImpl>(OpenModeKind::Read, directory, prefix, "Binary");
65  break;
66  case SerializerOpenModeWrite:
67  serializerImpl_ =
68  boost::make_shared<SerializerImpl>(OpenModeKind::Write, directory, prefix, "Binary");
69  break;
70  case SerializerOpenModeAppend:
71  serializerImpl_ =
72  boost::make_shared<SerializerImpl>(OpenModeKind::Append, directory, prefix, "Binary");
73  break;
74  }
75  } catch(Exception& e) {
76  internal::throwSerializationException("Error: %s", e.what());
77  }
78 
79  // Initialize MetainfoSet
80  globalMetainfo_.setImpl(
81  internal::make_shared_ptr<MetainfoMapImpl>(serializerImpl_->globalMetainfoPtr()));
82 
83  // Initialize savepoint vector
84  for(auto& savepoint : serializerImpl_->savepoints())
85  savepoints_.emplace_back(internal::make_shared_ptr(savepoint));
86 
87  // Initialize data field infos
88  for(auto it = serializerImpl_->fieldMap().begin(), end = serializerImpl_->fieldMap().end();
89  it != end; ++it)
90  datafieldInfos_.insert({it->first, internal::make_shared_ptr<FieldMetainfoImpl>(it->second)});
91 }
92 
93 bool Serializer::RegisterField(const std::string& name, std::string type, int bytesPerElement,
94  int iSize, int jSize, int kSize, int lSize, int iMinusHalo,
95  int iPlusHalo, int jMinusHalo, int jPlusHalo, int kMinusHalo,
96  int kPlusHalo, int lMinusHalo, int lPlusHalo) {
97  try {
98  TypeID typeID = internal::TypeNameToTypeID(type);
99  if(bytesPerElement != TypeUtil::sizeOf(typeID))
100  throw Exception("inconsistent bytes-per-element: got '%i' but according to passed type "
101  "'%s' expected '%i'",
102  bytesPerElement, type, TypeUtil::sizeOf(typeID));
103 
104  int rank =
105  (iSize != 1 ? 1 : 0) + (jSize != 1 ? 1 : 0) + (kSize != 1 ? 1 : 0) + (lSize != 1 ? 1 : 0);
106 
107  std::vector<int> dims{iSize, jSize, kSize, lSize};
108  MetainfoMapImpl metaInfo;
109  metaInfo.insert("__name", name);
110  metaInfo.insert("__elementtype", type);
111  metaInfo.insert("__bytesperelement", bytesPerElement);
112  metaInfo.insert("__rank", rank);
113  metaInfo.insert("__isize", iSize);
114  metaInfo.insert("__jsize", jSize);
115  metaInfo.insert("__ksize", kSize);
116  metaInfo.insert("__lsize", lSize);
117  metaInfo.insert("__iminushalosize", iMinusHalo);
118  metaInfo.insert("__iplushalosize", iPlusHalo);
119  metaInfo.insert("__jminushalosize", jMinusHalo);
120  metaInfo.insert("__jplushalosize", jPlusHalo);
121  metaInfo.insert("__kminushalosize", kMinusHalo);
122  metaInfo.insert("__kplushalosize", kPlusHalo);
123  metaInfo.insert("__lminushalosize", lMinusHalo);
124  metaInfo.insert("__lplushalosize", lPlusHalo);
125 
126  FieldMetainfoImpl fieldMetainfo(typeID, dims, metaInfo);
127 
128  // Field was already registered with the same meta-data
129  if(serializerImpl_->hasField(name) &&
130  (serializerImpl_->getFieldMetainfoImplOf(name) == fieldMetainfo)) {
131  return false;
132  }
133 
134  serializerImpl_->registerField(name, fieldMetainfo);
135 
136  // Keep the frontend data-structure up to date
137  auto it = serializerImpl_->fieldMap().findField(name);
138  datafieldInfos_.insert({it->first, internal::make_shared_ptr<FieldMetainfoImpl>(it->second)});
139 
140  } catch(Exception& e) {
141  internal::throwSerializationException("Error: %s", e.what());
142  }
143  return true;
144 }
145 
146 const DataFieldInfo& Serializer::FindField(const std::string& fieldname) const {
147  try {
148  auto it = datafieldInfos_.find(fieldname);
149  if(it == datafieldInfos_.end())
150  throw Exception("field %s is not registered", fieldname);
151  return it->second;
152 
153  } catch(Exception& e) {
154  internal::throwSerializationException("Error: %s", e.what());
155  }
156 }
157 
158 void Serializer::AddFieldMetainfo(const std::string& fieldname, const std::string& key,
159  bool value) {
160  try {
161  if(!serializerImpl_->addFieldMetainfoImpl(fieldname, key, value))
162  throw Exception("metainfo with key = %s exists already in field %s", key, fieldname);
163  } catch(Exception& e) {
164  internal::throwSerializationException("Error: %s", e.what());
165  }
166 }
167 
168 void Serializer::AddFieldMetainfo(const std::string& fieldname, const std::string& key, int value) {
169  try {
170  if(!serializerImpl_->addFieldMetainfoImpl(fieldname, key, value))
171  throw Exception("metainfo with key = %s exists already in field %s", key, fieldname);
172  } catch(Exception& e) {
173  internal::throwSerializationException("Error: %s", e.what());
174  }
175 }
176 
177 void Serializer::AddFieldMetainfo(const std::string& fieldname, const std::string& key,
178  float value) {
179  try {
180  if(!serializerImpl_->addFieldMetainfoImpl(fieldname, key, value))
181  throw Exception("metainfo with key = %s exists already in field %s", key, fieldname);
182  } catch(Exception& e) {
183  internal::throwSerializationException("Error: %s", e.what());
184  }
185 }
186 
187 void Serializer::AddFieldMetainfo(const std::string& fieldname, const std::string& key,
188  double value) {
189  try {
190  if(!serializerImpl_->addFieldMetainfoImpl(fieldname, key, value))
191  throw Exception("metainfo with key = %s exists already in field %s", key, fieldname);
192  } catch(Exception& e) {
193  internal::throwSerializationException("Error: %s", e.what());
194  }
195 }
196 
197 void Serializer::AddFieldMetainfo(const std::string& fieldname, const std::string& key,
198  std::string value) {
199  try {
200  if(!serializerImpl_->addFieldMetainfoImpl(fieldname, key, value))
201  throw Exception("metainfo with key = %s exists already in field %s", key, fieldname);
202  } catch(Exception& e) {
203  internal::throwSerializationException("Error: %s", e.what());
204  }
205 }
206 
207 std::vector<std::string> Serializer::fieldnames() const { return serializerImpl_->fieldnames(); }
208 
209 std::vector<std::string> Serializer::FieldsAtSavepoint(const Savepoint& savepoint) const {
210  std::vector<std::string> fields;
211 
212  // Check if savepoint exists
213  int idx = serializerImpl_->savepointVector().find(*savepoint.getImpl());
214  if(idx != -1) {
215  // Iterate fields per savepoint
216  const auto& fieldsPerSavepointMap = serializerImpl_->savepointVector().fieldsOf(idx);
217  for(auto it = fieldsPerSavepointMap.begin(), end = fieldsPerSavepointMap.end(); it != end; ++it)
218  fields.push_back(it->first);
219  }
220  return fields;
221 }
222 
223 static StorageView makeStorageView(const void* pData, TypeID type, const std::vector<int>& dims,
224  std::vector<int> strides) {
225 
226  int bytesPerElement = TypeUtil::sizeOf(type);
227 
228  // The StorageView operates on strides per type (not per byte)
229  for(std::size_t i = 0; i < dims.size(); ++i)
230  strides[i] /= bytesPerElement;
231 
232  // Check dimensions (strides.size() == 4 is guaranteed)
233  if(dims.size() > 4)
234  throw Exception("the STELLA frontend does not support %i dimensional storages", dims.size());
235 
236  // Adjust strides s.t dims.size() == strides.size()
237  while(strides.size() != dims.size())
238  strides.pop_back();
239 
240  return StorageView(const_cast<void*>(pData), type, dims, std::vector<int>(strides));
241 }
242 
243 void Serializer::WriteField(const std::string& fieldName, const Savepoint& savepoint,
244  const void* pData, int iStride, int jStride, int kStride, int lStride) {
246  return;
247 
248  try {
249  std::size_t numSavepoints = serializerImpl_->savepointVector().size();
250  const FieldMetainfoImpl& info = serializerImpl_->getFieldMetainfoImplOf(fieldName);
251 
252  StorageView storageView =
253  makeStorageView(pData, info.type(), info.dims(), {iStride, jStride, kStride, lStride});
254 
255  serializerImpl_->write(fieldName, *savepoint.getImpl(), storageView);
256 
257  // Keep the frontend data-structure up to date
258  if(numSavepoints < serializerImpl_->savepointVector().size())
259  savepoints_.emplace_back(
260  internal::make_shared_ptr<SavepointImpl>(serializerImpl_->savepointVector().back()));
261 
262  } catch(Exception& e) {
263  internal::throwSerializationException("Error: %s", e.what());
264  }
265 }
266 
267 void Serializer::ReadField(const std::string& fieldName, const Savepoint& savepoint, void* pData,
268  int iStride, int jStride, int kStride, int lStride,
269  bool alsoPrevious) const {
271  return;
272 
273  try {
274  const FieldMetainfoImpl& info = serializerImpl_->getFieldMetainfoImplOf(fieldName);
275 
276  StorageView storageView =
277  makeStorageView(pData, info.type(), info.dims(), {iStride, jStride, kStride, lStride});
278 
279  serializerImpl_->read(fieldName, *savepoint.getImpl(), storageView, alsoPrevious);
280 
281  } catch(Exception& e) {
282  internal::throwSerializationException("Error: %s", e.what());
283  }
284 }
285 
286 std::string Serializer::ToString() const {
287  std::ostringstream ss;
288  ss << serializerImpl_;
289  return ss.str();
290 }
291 
292 } // namespace stella
293 
294 } // namespace serialbox
static void EnableSerialization()
Enable serialization.
Definition: Serializer.cpp:43
std::vector< std::string > fieldnames() const
Gives access to the registered fields.
Definition: Serializer.cpp:207
Information of a data-field.
Definition: DataFieldInfo.h:31
bool insert(KeyType &&key, ValueType &&value) noexcept
Insert a new element in the map.
Meta-information of a data field.
static int serializationStatus() noexcept
Get the status of serialization.
void Init(const std::string &directory, const std::string &prefix, SerializerOpenMode mode)
Initializes the serializer.
Definition: Serializer.cpp:51
void ReadField(const std::string &fieldName, const Savepoint &savepoint, void *pData, int iStride, int jStride, int kStride, int lStride, bool alsoPrevious=false) const
Deserializes data from file.
Definition: Serializer.cpp:267
std::string ToString() const
Convert to string.
Definition: Serializer.cpp:286
std::string prefix() const
Prefix of the files.
Definition: Serializer.cpp:49
static int sizeOf(TypeID id)
Get size of the type.
Definition: Type.cpp:73
Represent a mutable view to a multi-dimensional storage.
Definition: StorageView.h:33
Namespace of the STELLA frontend.
Definition: ForwardDecl.h:27
Namespace of the serialbox library.
Definition: Archive.h:25
static void disableSerialization() noexcept
Disable serialization.
TypeID
Type-id of types recognized by serialbox.
Definition: Type.h:55
TypeID & type() noexcept
Access TypeID.
static void DisableSerialization()
Disable serialization.
Definition: Serializer.cpp:45
Implementation of the STELLA Savepoint.
Definition: Savepoint.h:30
std::vector< std::string > FieldsAtSavepoint(const Savepoint &savepoint) const
Gives all fields which are available at the given savepoint and return their names.
Definition: Serializer.cpp:209
SerializerOpenMode
OpenPolicy of the Serializer.
Definition: Serializer.h:43
Hash-map of meta-information of the form key = value pair or key = {value1, ..., valueN} ...
void setImpl(const boost::shared_ptr< MetainfoMapImpl > &metaInfoMap)
Set implementation pointer.
void AddFieldMetainfo(const std::string &fieldname, const std::string &key, bool value)
Adds a key-value metainformation pair to a field.
Definition: Serializer.cpp:158
bool RegisterField(const std::string &name, std::string type, int bytesPerElement, int iSize, int jSize, int kSize, int lSize, int iMinusHalo, int iPlusHalo, int jMinusHalo, int jPlusHalo, int kMinusHalo, int kPlusHalo, int lMinusHalo, int lPlusHalo)
Register a field into the serializer.
Definition: Serializer.cpp:93
const DataFieldInfo & FindField(const std::string &fieldname) const
Gives access to field info.
Definition: Serializer.cpp:146
static void enableSerialization() noexcept
Enable serialization.
SerializerOpenMode mode() const
Open mode.
Definition: Serializer.cpp:30
void WriteField(const std::string &fieldName, const Savepoint &savepoint, const void *pData, int iStride, int jStride, int kStride, int lStride)
Serializes data to file.
Definition: Serializer.cpp:243
boost::shared_ptr< SavepointImpl > & getImpl()
Get implementation pointer.
Definition: Savepoint.cpp:104
#define serialbox_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: Unreachable.h:41
Exception class which stores a human-readable error description.
Definition: Exception.h:30
std::string directory() const
Directory where the data are stored.
Definition: Serializer.cpp:47
std::vector< int > & dims() noexcept
Access dimensions.