3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 19:53:45 +01:00
dft_tools/triqs/utility/crash_logger.hpp
Olivier Parcollet f2c7d449cc First commit : triqs libs version 1.0 alpha1
for earlier commits, see TRIQS0.x repository.
2013-07-17 19:24:07 +02:00

96 lines
3.5 KiB
C++

/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_UTILITY_CRASH_LOGGER_H
#define TRIQS_UTILITY_CRASH_LOGGER_H
#include "./first_include.hpp"
#include <string>
#include <exception>
#include <stdexcept>
#include <functional>
#include <vector>
#include <iostream>
#include "./typeid_name.hpp"
#include "./scope_guard.hpp"
#include "../h5.hpp"
namespace triqs { namespace utility {
/**
* Usage :
*
* Suppose we have objects a,b,c ... which are all H5_Serializable
* Then :
* { // a scope, whatever
* auto log = crash_logger("dump.h5");
* log(a,"a")(b,"b")(c,"c"); // <---- pls make a macro here !
* // ... do some work
* log.dismiss();
* }
*
* Now : if the calculation proceeds correctly, nothing happens. log is destroyed.
* if however the calculation does not reach the dismiss, e.g. an exception occurs
* then log is destroyed without a dismiss and it will dump all objects in the hdf5 file.
*
* "some work" can be as complex as needed...
*
*/
class crash_logger {
std::string filename_;
std::vector<scope_guard<std::function<void()>>> guards;
std::vector<std::string> names;
public :
///
crash_logger(std::string filename) : filename_(filename){}
crash_logger(const crash_logger&) = delete;
crash_logger(crash_logger&&) = default;
crash_logger& operator=(const crash_logger&) = delete;
crash_logger& operator=(crash_logger && x) { using std::swap; swap(guards, x.guards); swap(names,x.names); return *this;}
///
template<typename Obj> crash_logger & operator()(Obj const & obj, std::string name) {
names.push_back(name);
guards.emplace_back([&obj,this, name](){
using triqs::h5::h5_write; // to have the proper overload for scalar type !!
try { h5_write( h5::group(H5::H5File(this->filename_.c_str(),H5F_ACC_RDWR)), name, obj); }
catch(H5::Exception const & e) { std::cerr << "An hdf5 exception has occurred in crash_logger : I can not recover : error is " <<std::endl ; e.printError();}
catch(...) { std::cerr << "An exception has occurred in crash_logger for an object of type " << typeid_name(obj) << " named " << name<< std::endl ; }
}); //end lambda
return *this;
}
///
~crash_logger() {
try {
if ((guards.size()>0) && (guards.front().active())) {
std::cerr << "crash_logger : I am destroyed without being dismissed. Dumping the objects : ";
for (auto & x : names) std::cerr<< "\""<< x <<"\" ";
std::cerr<< std::endl;
H5::H5File(this->filename_.c_str(),H5F_ACC_TRUNC); // create the file
}
}
catch(...) {} // just in case ... destructor can not throw
}
///
void dismiss() {for (auto & g : guards) g.dismiss();}
};
}}
#endif