libfoedus-core
FOEDUS Core Library
foedus::externalize::Externalizable Struct Referenceabstract

Represents an object that can be written to and read from files/bytes in XML format. More...

Detailed Description

Represents an object that can be written to and read from files/bytes in XML format.

Derived classes must implement load() and save().

Definition at line 53 of file externalizable.hpp.

#include <externalizable.hpp>

Inheritance diagram for foedus::externalize::Externalizable:

Public Member Functions

virtual ErrorStack load (tinyxml2::XMLElement *element)=0
 Reads the content of this object from the given XML element. More...
 
virtual ErrorStack save (tinyxml2::XMLElement *element) const =0
 Writes the content of this object to the given XML element. More...
 
virtual const char * get_tag_name () const =0
 Returns an XML tag name for this object as a root element. More...
 
virtual void assign (const foedus::externalize::Externalizable *other)=0
 Polymorphic assign operator. More...
 
ErrorStack load_from_string (const std::string &xml)
 Load the content of this object from the given XML string. More...
 
void save_to_stream (std::ostream *ptr) const
 Invokes save() and directs the resulting XML text to the given stream. More...
 
ErrorStack load_from_file (const fs::Path &path)
 Load the content of this object from the specified XML file. More...
 
ErrorStack save_to_file (const fs::Path &path) const
 Atomically and durably writes out this object to the specified XML file. More...
 

Static Public Member Functions

static ErrorStack insert_comment (tinyxml2::XMLElement *element, const std::string &comment)
 
static ErrorStack append_comment (tinyxml2::XMLElement *parent, const std::string &comment)
 
static ErrorStack create_element (tinyxml2::XMLElement *parent, const std::string &name, tinyxml2::XMLElement **out)
 
template<typename T >
static ErrorStack add_element (tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, T value)
 Only declaration in header. More...
 
template<uint MAXLEN, typename CHAR >
static ErrorStack add_element (tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, const assorted::FixedString< MAXLEN, CHAR > &value)
 
template<typename T >
static ErrorStack add_element (tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, const std::vector< T > &value)
 vector version More...
 
template<typename ENUM >
static ErrorStack add_enum_element (tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, ENUM value)
 enum version More...
 
static ErrorStack add_child_element (tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, const Externalizable &child)
 child Externalizable version More...
 
template<typename T >
static ErrorStack get_element (tinyxml2::XMLElement *parent, const std::string &tag, T *out, bool optional=false, T value=0)
 Only declaration in header. More...
 
static ErrorStack get_element (tinyxml2::XMLElement *parent, const std::string &tag, std::string *out, bool optional=false, const char *value="")
 string type is bit special. More...
 
template<uint MAXLEN, typename CHAR >
static ErrorStack get_element (tinyxml2::XMLElement *parent, const std::string &tag, assorted::FixedString< MAXLEN, CHAR > *out, bool optional=false, const assorted::FixedString< MAXLEN, CHAR > &value=assorted::FixedString< MAXLEN, CHAR >())
 
template<typename ENUM >
static ErrorStack get_enum_element (tinyxml2::XMLElement *parent, const std::string &tag, ENUM *out, bool optional=false, ENUM default_value=static_cast< ENUM >(0))
 enum version More...
 
template<typename T >
static ErrorStack get_element (tinyxml2::XMLElement *parent, const std::string &tag, std::vector< T > *out, bool optional=false)
 vector version. More...
 
static ErrorStack get_child_element (tinyxml2::XMLElement *parent, const std::string &tag, Externalizable *child, bool optional=false)
 child Externalizable version More...
 

Member Function Documentation

ErrorStack foedus::externalize::Externalizable::add_child_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
const std::string &  comment,
const Externalizable child 
)
static

child Externalizable version

Definition at line 221 of file externalizable.cpp.

References CHECK_ERROR, CHECK_OUTOFMEMORY, foedus::externalize::insert_comment_impl(), foedus::kRetOk, and save().

Referenced by foedus::log::LogOptions::save(), foedus::EngineOptions::save(), foedus::snapshot::SnapshotOptions::save(), foedus::storage::save_to_xml_array(), foedus::storage::save_to_xml_hash(), foedus::storage::save_to_xml_masstree(), and foedus::storage::save_to_xml_sequential().

222  {
223  tinyxml2::XMLElement* element = parent->GetDocument()->NewElement(tag.c_str());
224  CHECK_OUTOFMEMORY(element);
225  parent->InsertEndChild(element);
226  CHECK_ERROR(insert_comment_impl(element, comment));
227  CHECK_ERROR(child.save(element));
228  return kRetOk;
229 }
ErrorStack insert_comment_impl(tinyxml2::XMLElement *element, const std::string &comment)
#define CHECK_OUTOFMEMORY(ptr)
This macro checks if ptr is nullptr, and if so exists with kErrorCodeOutofmemory error stack...
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.

Here is the call graph for this function:

Here is the caller graph for this function:

template<typename T >
ErrorStack foedus::externalize::Externalizable::add_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
const std::string &  comment,
value 
)
static

Only declaration in header.

Explicitly instantiated in cpp for each type this func handles.

Definition at line 200 of file externalizable.cpp.

References CHECK_ERROR, CHECK_OUTOFMEMORY, foedus::externalize::insert_comment_impl(), and foedus::kRetOk.

Referenced by add_element(), add_enum_element(), foedus::storage::sequential::SequentialMetadataSerializer::save(), foedus::storage::hash::HashMetadataSerializer::save(), foedus::storage::array::ArrayMetadataSerializer::save(), foedus::storage::masstree::MasstreeMetadataSerializer::save(), and foedus::storage::MetadataSerializer::save_base().

201  {
202  tinyxml2::XMLElement* element = parent->GetDocument()->NewElement(tag.c_str());
203  CHECK_OUTOFMEMORY(element);
204  TinyxmlSetter<T> tinyxml_setter;
205  tinyxml_setter(element, value);
206  parent->InsertEndChild(element);
207  if (comment.size() > 0) {
209  tag + " (type=" + assorted::get_pretty_type_name<T>() + "): " + comment));
210  }
211  return kRetOk;
212 }
ErrorStack insert_comment_impl(tinyxml2::XMLElement *element, const std::string &comment)
#define CHECK_OUTOFMEMORY(ptr)
This macro checks if ptr is nullptr, and if so exists with kErrorCodeOutofmemory error stack...
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.

Here is the call graph for this function:

Here is the caller graph for this function:

template<uint MAXLEN, typename CHAR >
static ErrorStack foedus::externalize::Externalizable::add_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
const std::string &  comment,
const assorted::FixedString< MAXLEN, CHAR > &  value 
)
inlinestatic

Definition at line 134 of file externalizable.hpp.

References foedus::assorted::FixedString< MAXLEN, CHAR >::str().

138  {
139  return add_element< std::string >(parent, tag, comment, value.str());
140  }

Here is the call graph for this function:

template<typename T >
static ErrorStack foedus::externalize::Externalizable::add_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
const std::string &  comment,
const std::vector< T > &  value 
)
inlinestatic

vector version

Definition at line 144 of file externalizable.hpp.

References add_element(), append_comment(), CHECK_ERROR, foedus::assorted::get_pretty_type_name(), and foedus::kRetOk.

145  {
146  if (comment.size() > 0) {
148  tag + " (type=" + assorted::get_pretty_type_name< std::vector< T > >()
149  + "): " + comment));
150  }
151  for (std::size_t i = 0; i < value.size(); ++i) {
152  CHECK_ERROR(add_element(parent, tag, "", value[i]));
153  }
154  return kRetOk;
155  }
static ErrorStack append_comment(tinyxml2::XMLElement *parent, const std::string &comment)
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
std::string get_pretty_type_name()
Returns the name of the C++ type as readable as possible.
static ErrorStack add_element(tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, T value)
Only declaration in header.

Here is the call graph for this function:

template<typename ENUM >
static ErrorStack foedus::externalize::Externalizable::add_enum_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
const std::string &  comment,
ENUM  value 
)
inlinestatic

enum version

Definition at line 159 of file externalizable.hpp.

References add_element().

Referenced by foedus::storage::MetadataSerializer::save_base().

160  {
161  return add_element(parent, tag, comment, static_cast<int64_t>(value));
162  }
static ErrorStack add_element(tinyxml2::XMLElement *parent, const std::string &tag, const std::string &comment, T value)
Only declaration in header.

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorStack foedus::externalize::Externalizable::append_comment ( tinyxml2::XMLElement *  parent,
const std::string &  comment 
)
static

Definition at line 181 of file externalizable.cpp.

References CHECK_OUTOFMEMORY, and foedus::kRetOk.

Referenced by add_element().

182  {
183  if (comment.size() > 0) {
184  tinyxml2::XMLComment* cm = parent->GetDocument()->NewComment(comment.c_str());
185  CHECK_OUTOFMEMORY(cm);
186  parent->InsertEndChild(cm);
187  }
188  return kRetOk;
189 }
#define CHECK_OUTOFMEMORY(ptr)
This macro checks if ptr is nullptr, and if so exists with kErrorCodeOutofmemory error stack...
const ErrorStack kRetOk
Normal return value for no-error case.

Here is the caller graph for this function:

ErrorStack foedus::externalize::Externalizable::create_element ( tinyxml2::XMLElement *  parent,
const std::string &  name,
tinyxml2::XMLElement **  out 
)
static

Definition at line 191 of file externalizable.cpp.

References CHECK_OUTOFMEMORY, and foedus::kRetOk.

192  {
193  *out = parent->GetDocument()->NewElement(name.c_str());
194  CHECK_OUTOFMEMORY(*out);
195  parent->InsertEndChild(*out);
196  return kRetOk;
197 }
#define CHECK_OUTOFMEMORY(ptr)
This macro checks if ptr is nullptr, and if so exists with kErrorCodeOutofmemory error stack...
const ErrorStack kRetOk
Normal return value for no-error case.
ErrorStack foedus::externalize::Externalizable::get_child_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
Externalizable child,
bool  optional = false 
)
static

child Externalizable version

Definition at line 293 of file externalizable.cpp.

References ERROR_STACK_MSG, foedus::kErrorCodeConfMissingElement, foedus::kRetOk, and load().

Referenced by foedus::log::LogOptions::load(), foedus::EngineOptions::load(), and foedus::snapshot::SnapshotOptions::load().

294  {
295  tinyxml2::XMLElement* element = parent->FirstChildElement(tag.c_str());
296  if (element) {
297  return child->load(element);
298  } else {
299  if (optional) {
300  return kRetOk;
301  } else {
302  return ERROR_STACK_MSG(kErrorCodeConfMissingElement, tag.c_str());
303  }
304  }
305 }
0x0403 : "CONFIG : The xml element is missing in the config file." .
Definition: error_code.hpp:149
const ErrorStack kRetOk
Normal return value for no-error case.
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.

Here is the call graph for this function:

Here is the caller graph for this function:

template<typename T >
ErrorStack foedus::externalize::Externalizable::get_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
T *  out,
bool  optional = false,
value = 0 
)
static

Only declaration in header.

Explicitly instantiated in cpp for each type this func handles.

Definition at line 232 of file externalizable.cpp.

References ERROR_STACK_MSG, foedus::kErrorCodeConfInvalidElement, foedus::kErrorCodeConfMissingElement, and foedus::kRetOk.

Referenced by get_element(), foedus::storage::sequential::SequentialMetadataSerializer::load(), foedus::storage::hash::HashMetadataSerializer::load(), foedus::storage::array::ArrayMetadataSerializer::load(), foedus::storage::masstree::MasstreeMetadataSerializer::load(), foedus::storage::MetadataSerializer::load_all_storages_from_xml(), and foedus::storage::MetadataSerializer::load_base().

233  {
234  TinyxmlGetter<T> tinyxml_getter;
235  tinyxml2::XMLElement* element = parent->FirstChildElement(tag.c_str());
236  if (element) {
237  tinyxml2::XMLError xml_error = tinyxml_getter(element, out);
238  if (xml_error == tinyxml2::XML_SUCCESS) {
239  return kRetOk;
240  } else {
241  return ERROR_STACK_MSG(kErrorCodeConfInvalidElement, tag.c_str());
242  }
243  } else {
244  if (optional) {
245  *out = default_value;
246  return kRetOk;
247  } else {
248  return ERROR_STACK_MSG(kErrorCodeConfMissingElement, tag.c_str());
249  }
250  }
251 }
0x0404 : "CONFIG : An invalid valud in the xml element." .
Definition: error_code.hpp:150
0x0403 : "CONFIG : The xml element is missing in the config file." .
Definition: error_code.hpp:149
const ErrorStack kRetOk
Normal return value for no-error case.
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.

Here is the caller graph for this function:

ErrorStack foedus::externalize::Externalizable::get_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
std::string *  out,
bool  optional = false,
const char *  value = "" 
)
static

string type is bit special.

Definition at line 260 of file externalizable.cpp.

261  {
262  return get_element<std::string>(parent, tag, out, optional, std::string(default_value));
263 }
template<uint MAXLEN, typename CHAR >
static ErrorStack foedus::externalize::Externalizable::get_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
assorted::FixedString< MAXLEN, CHAR > *  out,
bool  optional = false,
const assorted::FixedString< MAXLEN, CHAR > &  value = assorted::FixedString<MAXLEN, CHAR>() 
)
inlinestatic

Definition at line 178 of file externalizable.hpp.

References foedus::assorted::FixedString< MAXLEN, CHAR >::assign(), CHECK_ERROR, get_element(), and foedus::kRetOk.

183  {
184  std::string tmp_out;
185  CHECK_ERROR(get_element(parent, tag, &tmp_out, optional, value.str().c_str()));
186  out->assign(tmp_out.data(), tmp_out.size());
187  return kRetOk;
188  }
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
static ErrorStack get_element(tinyxml2::XMLElement *parent, const std::string &tag, T *out, bool optional=false, T value=0)
Only declaration in header.

Here is the call graph for this function:

template<typename T>
ErrorStack foedus::externalize::Externalizable::get_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
std::vector< T > *  out,
bool  optional = false 
)
static

vector version.

Only declaration in header. Explicitly instantiated in cpp for each type this func handles.

Definition at line 266 of file externalizable.cpp.

References ERROR_STACK_MSG, foedus::kErrorCodeConfInvalidElement, foedus::kErrorCodeConfMissingElement, and foedus::kRetOk.

267  {
268  out->clear();
269  TinyxmlGetter<T> tinyxml_getter;
270  for (tinyxml2::XMLElement* element = parent->FirstChildElement(tag.c_str());
271  element; element = element->NextSiblingElement(tag.c_str())) {
272  T tmp;
273  tinyxml2::XMLError xml_error = tinyxml_getter(element, &tmp);
274  if (xml_error == tinyxml2::XML_SUCCESS) {
275  out->push_back(tmp); // vector<bool> doesn't support emplace_back!
276  } else {
277  return ERROR_STACK_MSG(kErrorCodeConfInvalidElement, tag.c_str());
278  }
279  }
280  if (out->size() == 0 && !optional) {
281  return ERROR_STACK_MSG(kErrorCodeConfMissingElement, tag.c_str());
282  }
283  return kRetOk;
284 }
0x0404 : "CONFIG : An invalid valud in the xml element." .
Definition: error_code.hpp:150
0x0403 : "CONFIG : The xml element is missing in the config file." .
Definition: error_code.hpp:149
const ErrorStack kRetOk
Normal return value for no-error case.
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.
template<typename ENUM >
static ErrorStack foedus::externalize::Externalizable::get_enum_element ( tinyxml2::XMLElement *  parent,
const std::string &  tag,
ENUM *  out,
bool  optional = false,
ENUM  default_value = static_cast<ENUM>(0) 
)
inlinestatic

enum version

Definition at line 192 of file externalizable.hpp.

References CHECK_ERROR, ERROR_STACK_MSG, foedus::kErrorCodeConfValueOutofrange, and foedus::kRetOk.

Referenced by foedus::storage::MetadataSerializer::load_all_storages_from_xml(), and foedus::storage::MetadataSerializer::load_base().

193  {
194  // enum might be signged or unsigned, 1 byte, 2 byte, or 4 byte.
195  // But surely it won't exceed int64_t range.
196  int64_t tmp;
197  CHECK_ERROR(get_element<int64_t>(parent, tag, &tmp, optional, default_value));
198  if (static_cast<int64_t>(static_cast<ENUM>(tmp)) != tmp) {
199  return ERROR_STACK_MSG(kErrorCodeConfValueOutofrange, tag.c_str());
200  }
201  *out = static_cast<ENUM>(tmp);
202  return kRetOk;
203  }
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
0x0402 : "CONFIG : Configuration value out of range." .
Definition: error_code.hpp:148
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.

Here is the caller graph for this function:

ErrorStack foedus::externalize::Externalizable::load_from_file ( const fs::Path path)

Load the content of this object from the specified XML file.

Parameters
[in]pathpath of the XML file.

Expect errors due to missing-elements, out-of-range values, etc.

Definition at line 75 of file externalizable.cpp.

References foedus::fs::Path::c_str(), CHECK_ERROR, ERROR_STACK_MSG, foedus::fs::exists(), foedus::kErrorCodeConfEmptyXml, foedus::kErrorCodeConfFileNotFount, foedus::kErrorCodeConfParseFailed, foedus::kRetOk, and load().

Referenced by foedus::savepoint::SavepointManagerPimpl::initialize_once(), and foedus::snapshot::SnapshotManagerPimpl::read_snapshot_metadata().

75  {
76  tinyxml2::XMLDocument document;
77  if (!fs::exists(path)) {
78  return ERROR_STACK_MSG(kErrorCodeConfFileNotFount, path.c_str());
79  }
80 
81  tinyxml2::XMLError load_error = document.LoadFile(path.c_str());
82  if (load_error != tinyxml2::XML_SUCCESS) {
83  std::stringstream custom_message;
84  custom_message << "problemtic file=" << path << ", tinyxml2 error=" << load_error
85  << ", GetErrorStr1()=" << document.GetErrorStr1()
86  << ", GetErrorStr2()=" << document.GetErrorStr2();
87  return ERROR_STACK_MSG(kErrorCodeConfParseFailed, custom_message.str().c_str());
88  } else if (!document.RootElement()) {
89  return ERROR_STACK_MSG(kErrorCodeConfEmptyXml, path.c_str());
90  } else {
91  CHECK_ERROR(load(document.RootElement()));
92  }
93  return kRetOk;
94 }
0x0406 : "CONFIG : The file doesn't exist." .
Definition: error_code.hpp:152
0x0401 : "CONFIG : Config file parsing failed. This usually means an invalid XML file." .
Definition: error_code.hpp:147
bool exists(const Path &p)
Returns if the file exists.
Definition: filesystem.hpp:128
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
0x0405 : "CONFIG : No root element in the xml." .
Definition: error_code.hpp:151
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.
virtual ErrorStack load(tinyxml2::XMLElement *element)=0
Reads the content of this object from the given XML element.

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorStack foedus::externalize::Externalizable::load_from_string ( const std::string &  xml)

Load the content of this object from the given XML string.

Parameters
[in]xmlXML string.

Expect errors due to missing-elements, out-of-range values, etc.

Definition at line 38 of file externalizable.cpp.

References CHECK_ERROR, ERROR_STACK_MSG, foedus::kErrorCodeConfEmptyXml, foedus::kErrorCodeConfParseFailed, foedus::kRetOk, and load().

Referenced by foedus::soc::SharedMemoryRepo::attach_shared_memories().

38  {
39  tinyxml2::XMLDocument document;
40  tinyxml2::XMLError load_error = document.Parse(xml.data(), xml.size());
41  if (load_error != tinyxml2::XML_SUCCESS) {
42  std::stringstream custom_message;
43  custom_message << "xml=" << xml << ", tinyxml2 error=" << load_error
44  << ", GetErrorStr1()=" << document.GetErrorStr1()
45  << ", GetErrorStr2()=" << document.GetErrorStr2();
46  return ERROR_STACK_MSG(kErrorCodeConfParseFailed, custom_message.str().c_str());
47  } else if (!document.RootElement()) {
48  return ERROR_STACK_MSG(kErrorCodeConfEmptyXml, xml.c_str());
49  } else {
50  CHECK_ERROR(load(document.RootElement()));
51  }
52  return kRetOk;
53 }
0x0401 : "CONFIG : Config file parsing failed. This usually means an invalid XML file." .
Definition: error_code.hpp:147
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
0x0405 : "CONFIG : No root element in the xml." .
Definition: error_code.hpp:151
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.
virtual ErrorStack load(tinyxml2::XMLElement *element)=0
Reads the content of this object from the given XML element.

Here is the call graph for this function:

Here is the caller graph for this function:

virtual ErrorStack foedus::externalize::Externalizable::save ( tinyxml2::XMLElement *  element) const
pure virtual

Writes the content of this object to the given XML element.

Parameters
[in]elementthe XML element that represents this object

Expect only out-of-memory error. We receive the XML element this object will represent, so this method does not determine the XML element name of itself. The parent object determines children's tag names because one parent object might have multiple child objects of the same type with different XML element name.

Implemented in foedus::snapshot::SnapshotOptions, foedus::EngineOptions, foedus::storage::masstree::MasstreeMetadataSerializer, foedus::memory::MemoryOptions, foedus::savepoint::Savepoint, foedus::log::LogOptions, foedus::debugging::DebuggingOptions, foedus::cache::CacheOptions, foedus::soc::SocOptions, foedus::storage::array::ArrayMetadataSerializer, foedus::storage::hash::HashMetadataSerializer, foedus::storage::sequential::SequentialMetadataSerializer, foedus::proc::ProcOptions, foedus::fs::DeviceEmulationOptions, foedus::thread::ThreadOptions, foedus::xct::XctOptions, foedus::storage::StorageOptions, foedus::snapshot::SnapshotMetadata, foedus::savepoint::SavepointOptions, and foedus::restart::RestartOptions.

Referenced by add_child_element(), save_to_file(), and save_to_stream().

Here is the caller graph for this function:

ErrorStack foedus::externalize::Externalizable::save_to_file ( const fs::Path path) const

Atomically and durably writes out this object to the specified XML file.

Parameters
[in]pathpath of the XML file.

If the file exists, this method atomically overwrites it via POSIX's atomic rename semantics. If the parent folder doesn't exist, this method automatically creates the folder. Expect errors due to file-permission (and other file I/O issue), out-of-memory, etc.

Definition at line 96 of file externalizable.cpp.

References foedus::memory::AlignedMemory::alloc(), CHECK_ERROR, CHECK_OUTOFMEMORY, foedus::fs::DirectIoFile::close(), foedus::fs::create_directories(), foedus::fs::durable_atomic_rename(), ERROR_STACK_MSG, foedus::fs::exists(), foedus::fs::fsync(), get_tag_name(), foedus::kErrorCodeConfCouldNotRename, foedus::kErrorCodeConfCouldNotWrite, foedus::kErrorCodeConfMkdirsFailed, foedus::memory::AlignedMemory::kPosixMemalign, foedus::kRetOk, foedus::fs::DirectIoFile::open(), foedus::assorted::os_error(), foedus::fs::Path::parent_path(), save(), foedus::fs::unique_name(), WRAP_ERROR_CODE, and foedus::fs::DirectIoFile::write().

Referenced by foedus::savepoint::SavepointManagerPimpl::initialize_once(), foedus::savepoint::SavepointManagerPimpl::savepoint_main(), and foedus::snapshot::SnapshotManagerPimpl::snapshot_metadata().

96  {
97  // construct the XML in memory
98  tinyxml2::XMLDocument document;
99  tinyxml2::XMLElement* root = document.NewElement(get_tag_name());
100  CHECK_OUTOFMEMORY(root);
101  document.InsertFirstChild(root);
102  CHECK_ERROR(save(root));
103 
104  fs::Path folder = path.parent_path();
105  // create the folder if not exists
106  if (!fs::exists(folder)) {
107  if (!fs::create_directories(folder, true)) {
108  std::stringstream custom_message;
109  custom_message << "file=" << path << ", folder=" << folder
110  << ", err=" << assorted::os_error();
111  return ERROR_STACK_MSG(kErrorCodeConfMkdirsFailed, custom_message.str().c_str());
112  }
113  }
114 
115  // Retrieve an XML representation. We initially used document.SaveFile(), but
116  // it is not ideal as it uses non-aligned non-O_DIRECT APIs.
117  // This caused a data loss in our NVDIMM environment.
118  tinyxml2::XMLPrinter xml_stream;
119  document.Print(&xml_stream);
120  const uint32_t non_aligned_size = xml_stream.CStrSize();
121  const uint32_t aligned_size = assorted::align<uint32_t, 1U << 12>(non_aligned_size);
122  memory::AlignedMemory xml_memory;
123  xml_memory.alloc(aligned_size, 1U << 12, memory::AlignedMemory::kPosixMemalign, 0);
124  if (xml_memory.is_null()) {
125  return ERROR_STACK_MSG(kErrorCodeConfCouldNotWrite, "Out of memory in posix_memalign");
126  }
127  char* buffer = reinterpret_cast<char*>(xml_memory.get_block());
128  std::memcpy(buffer, xml_stream.CStr(), non_aligned_size);
129  std::memset(buffer + non_aligned_size, '\n', aligned_size - non_aligned_size); // LF padding
130 
131  // To atomically save a file, we write to a temporary file and call sync, then use POSIX rename.
132  fs::Path tmp_path(path);
133  tmp_path += ".tmp_";
134  tmp_path += fs::unique_name("%%%%%%%%");
135 
136  {
137  // Use Direct I/O to save this file. For all critical files, we always use
138  // open/write with O_DIRECT.
139  fs::DirectIoFile tmp_file(tmp_path);
140  WRAP_ERROR_CODE(tmp_file.open(false, true, true, true));
141  WRAP_ERROR_CODE(tmp_file.write(aligned_size, xml_memory));
142  tmp_file.close();
143  // TASK(Hideaki) We should not need the following fsync. Let's test this later.
144  // For now, do a safer thing.
145  fs::fsync(tmp_path, true);
146  }
147 
148  if (!fs::durable_atomic_rename(tmp_path, path)) {
149  std::stringstream custom_message;
150  custom_message << "dest file=" << path << ", src file=" << tmp_path
151  << ", err=" << assorted::os_error();
152  return ERROR_STACK_MSG(kErrorCodeConfCouldNotRename, custom_message.str().c_str());
153  }
154 
155  return kRetOk;
156 }
0x0408 : "CONFIG : Failed to atomically rename the temporary file to destination." ...
Definition: error_code.hpp:154
#define CHECK_OUTOFMEMORY(ptr)
This macro checks if ptr is nullptr, and if so exists with kErrorCodeOutofmemory error stack...
0x0409 : "CONFIG : Failed to create a directory. Check permissions." .
Definition: error_code.hpp:155
0x0407 : "CONFIG : Failed to write a configuration file." .
Definition: error_code.hpp:153
bool durable_atomic_rename(const Path &old_path, const Path &new_path)
fsync() on source file before rename, then fsync() on the parent folder after rename.
Definition: filesystem.cpp:236
bool create_directories(const Path &p, bool sync=false)
Recursive mkdir (mkdirs).
Definition: filesystem.cpp:89
bool exists(const Path &p)
Returns if the file exists.
Definition: filesystem.hpp:128
virtual const char * get_tag_name() const =0
Returns an XML tag name for this object as a root element.
std::string os_error()
Thread-safe strerror(errno).
virtual ErrorStack save(tinyxml2::XMLElement *element) const =0
Writes the content of this object to the given XML element.
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
std::string unique_name(uint64_t differentiator=0)
Equivalent to unique_path("%%%%-%%%%-%%%%-%%%%").
Definition: filesystem.cpp:174
const ErrorStack kRetOk
Normal return value for no-error case.
#define ERROR_STACK_MSG(e, m)
Overload of ERROR_STACK(e) to receive a custom error message.
#define WRAP_ERROR_CODE(x)
Same as CHECK_ERROR(x) except it receives only an error code, thus more efficient.
bool fsync(const Path &path, bool sync_parent_directory=false)
Makes the content and metadata of the file durable all the way up to devices.
Definition: filesystem.cpp:203

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::externalize::Externalizable::save_to_stream ( std::ostream *  ptr) const

Invokes save() and directs the resulting XML text to the given stream.

Parameters
[in]ptrostream to write to.

Definition at line 55 of file externalizable.cpp.

References get_tag_name(), foedus::ErrorStack::is_error(), and save().

Referenced by foedus::soc::SharedMemoryRepo::allocate_shared_memories().

55  {
56  std::ostream &o = *ptr;
57  tinyxml2::XMLDocument doc;
58  // root element name is class name.
59  tinyxml2::XMLElement* element = doc.NewElement(get_tag_name());
60  if (!element) {
61  o << "Out-of-memory during Externalizable::save_to_stream()";
62  return;
63  }
64  doc.InsertFirstChild(element);
65  ErrorStack error_stack = save(element);
66  if (error_stack.is_error()) {
67  o << "Failed during Externalizable::save_to_stream(): " << error_stack;
68  return;
69  }
70  tinyxml2::XMLPrinter printer;
71  doc.Print(&printer);
72  o << printer.CStr();
73 }
virtual const char * get_tag_name() const =0
Returns an XML tag name for this object as a root element.
virtual ErrorStack save(tinyxml2::XMLElement *element) const =0
Writes the content of this object to the given XML element.

Here is the call graph for this function:

Here is the caller graph for this function:


The documentation for this struct was generated from the following files: