17#ifndef __B2DATABASE_H__ 
   18#define __B2DATABASE_H__ 
   29#include "b2ppconfig.h" 
   30#include "utils/b2linear_algebra.H" 
   33#include "utils/b2rtable.H" 
   34#include "utils/b2time.H" 
   36extern "C" int _mcDBopenFile(
 
   37      int handle, 
const char* filename, 
const char* ftype, mcSize npage, mcSize lpage);
 
   39inline std::string mcErrGetMsgAndReset(
int code) {
 
   40    const char* err_msg = mcErrGetMsg(code);
 
   41    std::string res = err_msg ? err_msg : 
"Invalid MemCom error code";
 
   55    operator const char*() 
const { 
return c_str(); }
 
   56    template <
typename T1>
 
   60        std::string::operator=(o.str());
 
   62    template <
typename T1, 
typename T2>
 
   63    SetName(
const T1& a1, 
const T2& a2) {
 
   66        std::string::operator=(o.str());
 
   68    template <
typename T1, 
typename T2, 
typename T3>
 
   69    SetName(
const T1& a1, 
const T2& a2, 
const T3& a3) {
 
   71        o << a1 << 
"." << a2 << 
"." << a3;
 
   72        std::string::operator=(o.str());
 
   74    template <
typename T1, 
typename T2, 
typename T3, 
typename T4>
 
   75    SetName(
const T1& a1, 
const T2& a2, 
const T3& a3, 
const T4& a4) {
 
   77        o << a1 << 
"." << a2 << 
"." << a3 << 
"." << a4;
 
   78        std::string::operator=(o.str());
 
   80    template <
typename T1, 
typename T2, 
typename T3, 
typename T4, 
typename T5>
 
   81    SetName(
const T1& a1, 
const T2& a2, 
const T3& a3, 
const T4& a4, 
const T5& a5) {
 
   83        o << a1 << 
"." << a2 << 
"." << a3 << 
"." << a4 << 
"." << a5;
 
   84        std::string::operator=(o.str());
 
   87    SetName& gname(
const std::string& gname_) {
 
   88        replace_field(0, gname_);
 
   93    SetName& gname(
const T& gname_) {
 
   96        return gname(o.str());
 
   99    std::string get_gname()
 const { 
return substr_field(0); }
 
  101    bool gname_undef()
 const { 
return is_undef(0); }
 
  103    SetName& branch(
const std::string& branch_) {
 
  104        replace_field(1, branch_);
 
  108    template <
typename T>
 
  109    SetName& branch(
const T& branch_) {
 
  110        std::ostringstream o;
 
  112        return branch(o.str());
 
  115    std::string get_branch()
 const { 
return substr_field(1); }
 
  117    bool branch_undef()
 const { 
return is_undef(1); }
 
  119    SetName& cycle(
const std::string& cycle_) {
 
  120        replace_field(2, cycle_);
 
  124    template <
typename T>
 
  125    SetName& cycle(
const T& cycle_) {
 
  126        std::ostringstream o;
 
  128        return cycle(o.str());
 
  131    std::string get_cycle()
 const { 
return substr_field(2); }
 
  133    bool cycle_undef()
 const { 
return is_undef(2); }
 
  135    SetName& subcycle(
const std::string& subcycle_) {
 
  136        replace_field(3, subcycle_);
 
  140    template <
typename T>
 
  141    SetName& subcycle(
const T& subcycle_) {
 
  142        std::ostringstream o;
 
  144        return subcycle(o.str());
 
  147    std::string get_subcycle()
 const { 
return substr_field(3); }
 
  149    bool subcycle_undef()
 const { 
return is_undef(3); }
 
  151    SetName& case_(
const std::string& case__) {
 
  152        replace_field(4, case__);
 
  156    template <
typename T>
 
  157    SetName& case_(
const T& case__) {
 
  158        std::ostringstream o;
 
  160        return case_(o.str());
 
  163    std::string get_case()
 const { 
return substr_field(4); }
 
  165    bool case_undef()
 const { 
return is_undef(4); }
 
  167    SetName& subcase(
const std::string& subcase_) {
 
  168        replace_field(5, subcase_);
 
  172    template <
typename T>
 
  173    SetName& subcase(
const T& subcase_) {
 
  174        std::ostringstream o;
 
  176        return subcase(o.str());
 
  179    std::string get_subcase()
 const { 
return substr_field(5); }
 
  181    bool subcase_undef()
 const { 
return is_undef(5); }
 
  183    bool match(
const std::string& pattern)
 const {
 
  184        return (fnmatch(pattern.c_str(), c_str(), 0) == 0);
 
  188    void replace_field(
int pos, 
const std::string& s) {
 
  189        const int pos_save = pos;
 
  192            if ((begin_ = std::string::find(
".", begin_)) == -1) {
 
  195                    begin_ = std::string::size() - 1;
 
  198                    begin_ = std::string::size();
 
  204        int end_ = std::string::find(
".", begin_);
 
  205        std::string::replace(begin_, (end_ == -1 ? std::string::size() : end_) - begin_, s);
 
  208        if (pos_save == 5 && s == 
"0") { resize(begin_ - 1); }
 
  211    std::string substr_field(
int pos)
 const {
 
  214            if ((begin_ = std::string::find(
".", begin_)) == -1) { 
return ""; }
 
  217        int end_ = std::string::find(
".", begin_);
 
  218        return std::string::substr(begin_, (end_ == -1 ? std::string::size() : end_) - begin_);
 
  221    bool is_undef(
int pos)
 const {
 
  222        std::string tmp = substr_field(pos);
 
  223        return tmp.empty() || tmp == 
"0" || tmp == 
"*";
 
 
  232    static const char* name;
 
 
  256typedef std::vector<RTable> ArrayRTable;
 
  262    DBSlice(mcOff start_, mcOff end_ = 0, mcOff step_ = 1)
 
  263        : start(start_), end(end_ == 0 ? start_ + 1 : end_), step(step_) {}
 
  265    size_t size()
 const { 
return (end - start) / step; }
 
  267    bool is_null()
 const { 
return this == &null; }
 
  269    bool is_all()
 const { 
return this == &all; }
 
  271    void set_mcslice(mcSlice* sl)
 const {
 
  272        sl->start = start + 1;
 
 
  293          close_db_on_delete(
true),
 
  300    void init(
const std::string& name);
 
  305    std::string get_logging_directory();
 
  308    void open(
bool readonly = 
false);
 
  313            int status = mcDBcloseFile(handler);
 
  314            if (status < 0) { 
IOError() << mcErrGetMsgAndReset(status) << 
THROW; }
 
 
  324        return (mcDBinqSetAtt(handler, key.c_str(), 
nullptr) == 1);
 
 
  334        for (
int iter = 0; mcDBgetSetNextIter(handler, &iter, &att);) {
 
  336            if (set_name.match(pattern)) { set_names.insert(set_name); }
 
 
  343        int status = mcDBsaveFileNoSync(handler);
 
  344        if (status < 0) { 
IOError() << mcErrGetMsgAndReset(status) << 
THROW; }
 
  346        time_sync = double(t2 - t1) * 10;
 
 
  354        if (
double(Time() - last_sync) > time_sync) { 
sync(); }
 
 
  357    virtual void temporary_close() {
 
  358        int status = mcDBcloseFile(handler);
 
  359        if (status < 0) { 
IOError() << mcErrGetMsgAndReset(status) << 
THROW; }
 
  362    virtual void reopen() {
 
  363        std::string arch_path = 
path::join(db_name, 
"archives.mc");
 
  364        if (_mcDBopenFile(handler, arch_path.c_str(), (is_readonly ? 
"o" : 
"rw"), 0, 0)
 
  366            IOError() << 
"Cannot reopen the B2000++ database \"" << db_name << 
"\"." << 
THROW;
 
  370    class TemporaryClose {
 
  372        TemporaryClose(DataBase& db_) : db(db_) { db.temporary_close(); }
 
  373        ~TemporaryClose() { db.reopen(); }
 
  380    size_t ndim(
const std::string& key)
 const {
 
  382        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  383            DBError() << 
"The dataset " << key << 
" does not exist." << 
THROW;
 
 
  389    const std::vector<size_t> 
dims(
const std::string& key)
 const {
 
  391        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  392            DBError() << 
"The dataset " << key << 
" does not exist." << 
THROW;
 
  394        return std::vector<size_t>(att.dim, att.dim + att.ndim);
 
 
  400        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  401            DBError() << 
"The dataset " << key << 
" does not exist." << 
THROW;
 
  403        switch (att.type[0]) {
 
  405                return typeid(mcInt32);
 
  407                return typeid(mcInt64);
 
  409                return typeid(mcFloat32);
 
  411                return typeid(mcFloat64);
 
  413                return typeid(std::complex<mcFloat64>);
 
  415                return typeid(std::complex<mcFloat64>);
 
  417                return typeid(std::string);
 
  421                if (att.type[0] == 
'S' && att.type[0] == 
'T') { 
return typeid(ArrayRTable); }
 
  422                DBError() << 
"The memcom type " << att.type << 
" is not supported by B2000++" 
 
  431        int status = mcDBdeleteSet(handler, key.c_str());
 
  433            DBError() << 
"mcDBdeleteSet returns an unexpected error: " 
  434                      << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  439    void rename(
const std::string& oldkey, 
const std::string& newkey) {
 
  441        int status = mcDBrenameSet(handler, oldkey.c_str(), newkey.c_str());
 
  443            DBError() << 
"mcDBrenameSet returns an unexpected error: " 
  444                      << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  448    mcSetAttributes get_attributes(
const std::string& key)
 const {
 
  450        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  451            DBError() << 
"The dataset " << key << 
" does not exist." << 
THROW;
 
  457    template <
typename T>
 
  458    void get(
const std::string& key, std::vector<T>& v, 
const DBSlice& s1 = DBSlice::all)
 const {
 
  460        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  461            DBError() << 
"Cannot read dataset " << key << 
", it does not exist." << 
THROW;
 
  463        if (att.ndim != 1 && att.dim[1] != 1) {
 
  464            DBError() << 
"Cannot read dataset " << key << 
", it has " << att.ndim
 
  465                      << 
" instead of 1 dimensions." << 
THROW;
 
  467        bool convert = 
false;
 
  470                DBError() << 
"Cannot read dataset " << key << 
", its type is " << att.type
 
  478                v.resize(att.dim[0]);
 
  482        } 
else if (s1.is_all()) {
 
  483            if (mcOff(v.size()) != att.dim[0]) {
 
  484                DBError() << 
"Cannot read dataset " << key << 
", its first dimension is " 
  485                          << att.dim[0] << 
" instead of " << v.size() << 
"." << 
THROW;
 
  487        } 
else if (v.size() != s1.size()) {
 
  488            DBError() << 
"Cannot read dataset " << key << 
", the size of the vector is " << v.size()
 
  489                      << 
" but the size of the DBSlice is " << s1.size() << 
"." << 
THROW;
 
  492        void* p = (
void*)&v[0];
 
  493        std::vector<char> tmp;
 
  495            tmp.resize(mcSizeof(att.type) * v.size());
 
  500            int status = mcDBgetSetArray(handler, key.c_str(), v.size(), p);
 
  502                DBError() << 
"mcDBgetSetposArray returns an unexpected error: " 
  503                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  508            int status = mcDBgetSetsliceArray(handler, key.c_str(), 1, &sl, 0, 
nullptr, p);
 
  510                DBError() << 
"mcDBgetSetsliceArray returns an unexpected error: " 
  511                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  519    template <
typename T>
 
  522        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  523            DBError() << 
"Cannot read dataset " << key << 
", it does not exist." << 
THROW;
 
  526            DBError() << 
"Cannot read dataset " << key << 
", it has " << att.ndim
 
  527                      << 
" instead of 2 dimensions." << 
THROW;
 
  529        bool convert = 
false;
 
  532                DBError() << 
"Cannot read dataset " << key << 
", its type is " << att.type
 
  539                v.resize(att.dim[0]);
 
  543        } 
else if (s1.is_all()) {
 
  544            if (mcOff(v.size()) != att.dim[0]) {
 
  545                DBError() << 
"Cannot read dataset " << key << 
", its first dimension is " 
  546                          << att.dim[0] << 
" instead of " << v.size() << 
"." << 
THROW;
 
  548        } 
else if (v.size() != s1.size()) {
 
  549            DBError() << 
"Cannot read dataset " << key << 
", the size of the vector is " << v.size()
 
  550                      << 
" but the size of the DBSlice is " << s1.size() << 
"." << 
THROW;
 
  552        if (s2.is_all() || s2.size() != 1) {
 
  553            DBError() << 
"The DBSlice " << key << 
" has not dimension 1." << 
THROW;
 
  556        void* p = (
void*)&v[0];
 
  557        std::vector<char> tmp;
 
  559            tmp.resize(mcSizeof(att.type) * v.size());
 
  565                  mcDBgetSetposArray(handler, key.c_str(), att.dim[0] * s2.start + 1, v.size(), p);
 
  567                DBError() << 
"mcDBgetSetposArray returns an unexpected error: " 
  568                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  573            s1.set_mcslice(sl + 1);
 
  574            int status = mcDBgetSetsliceArray(handler, key.c_str(), 1, sl, 0, 
nullptr, p);
 
  576                DBError() << 
"mcDBgetSetsliceArray returns an unexpected error: " 
  577                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  585    template <
typename T>
 
  587          const std::string& key, b2linalg::Vector<T, b2linalg::Vincrement_ref> v,
 
  588          const DBSlice& s1 = DBSlice::all) {
 
  590        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  591            DBError() << 
"Cannot read dataset " << key << 
", it does not exist." << 
THROW;
 
  594            DBError() << 
"Cannot read dataset " << key << 
", it has " << att.ndim
 
  595                      << 
" instead of 1 dimensions." << 
THROW;
 
  597        bool convert = 
false;
 
  600                DBError() << 
"Cannot read dataset " << key << 
", its type is " << att.type
 
  607            if (mcOff(v.size()) != att.dim[0]) {
 
  608                DBError() << 
"Cannot read dataset " << key << 
" its first dimension is " 
  609                          << att.dim[0] << 
" instead of " << v.size() << 
"." << 
THROW;
 
  611        } 
else if (v.size() != s1.size()) {
 
  612            DBError() << 
"Cannot read dataset " << key << 
", the size of the vector is " << v.size()
 
  613                      << 
" but the size of the DBSlice is " << s1.size() << 
"." << 
THROW;
 
  616        void* p = (
void*)&v[0];
 
  617        std::vector<char> tmp;
 
  619            tmp.resize(mcSizeof(att.type) * v.size());
 
  624            int status = mcDBgetSetArray(handler, key.c_str(), v.size(), p);
 
  626                DBError() << 
"mcDBgetSetposArray returns an unexpected error: " 
  627                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  632            int status = mcDBgetSetsliceArray(handler, key.c_str(), 1, &sl, 0, 
nullptr, p);
 
  634                DBError() << 
"mcDBgetSetsliceArray returns an unexpected error: " 
  635                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  643    template <
typename T>
 
  645          const std::string& key, b2linalg::Vector<T, b2linalg::Vincrement_ref> v,
 
  648        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  649            DBError() << 
"Cannot read dataset " << key << 
", it does not exist." << 
THROW;
 
  652            DBError() << 
"Cannot read dataset " << key << 
", it has " << att.ndim
 
  653                      << 
" instead of 2 dimensions." << 
THROW;
 
  655        bool convert = 
false;
 
  658                DBError() << 
"Cannot read dataset " << key << 
" its type is " << att.type
 
  665            if (mcOff(v.size()) != att.dim[0]) {
 
  666                DBError() << 
"Cannot read dataset " << key << 
" its first dimension is " 
  667                          << att.dim[0] << 
" instead of " << v.size() << 
"." << 
THROW;
 
  669        } 
else if (v.size() != s1.size()) {
 
  670            DBError() << 
"Cannot read dataset " << key << 
", the size of the vector is " << v.size()
 
  671                      << 
" but the size of the DBSlice is " << s1.size() << 
"." << 
THROW;
 
  673        if (s2.is_all() || s2.size() != 1) {
 
  674            DBError() << 
"Cannot read dataset " << key << 
", the DBSlice " << key
 
  675                      << 
" has not dimension 1." << 
THROW;
 
  678        void* p = (
void*)&v[0];
 
  679        std::vector<char> tmp;
 
  681            tmp.resize(mcSizeof(att.type) * v.size());
 
  687                  mcDBgetSetposArray(handler, key.c_str(), att.dim[0] * s2.start + 1, v.size(), p);
 
  689                DBError() << 
"mcDBgetSetposArray returns an unexpected error: " 
  690                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  695            s1.set_mcslice(sl + 1);
 
  696            int status = mcDBgetSetsliceArray(handler, key.c_str(), 1, sl, 0, 
nullptr, p);
 
  698                DBError() << 
"mcDBgetSetsliceArray returns an unexpected error: " 
  699                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  707    template <
typename T>
 
  709          const std::string& key, b2linalg::Matrix<T, b2linalg::Mrectangle>& m,
 
  710          const DBSlice& s1 = DBSlice::all, 
const DBSlice& s2 = DBSlice::all) {
 
  712        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  713            DBError() << 
"Cannot read dataset " << key << 
", it does not exist." << 
THROW;
 
  716            DBError() << 
"Cannot read dataset " << key << 
", it has " << att.ndim
 
  717                      << 
" instead of 2 dimensions." << 
THROW;
 
  719        bool convert = 
false;
 
  722                DBError() << 
"Cannot read dataset " << key << 
", its type is " << att.type
 
  728        if (m.size1() != 0) {
 
  730                if (mcOff(m.size1()) != att.dim[1]) {
 
  731                    DBError() << 
"Cannot read dataset set " << key << 
", its first dimension is " 
  732                              << att.dim[1] << 
" instead of " << m.size1() << 
"." << 
THROW;
 
  734            } 
else if (m.size1() != s1.size()) {
 
  735                DBError() << 
"Cannot read dataset " << key
 
  736                          << 
", the first dimension of the matrix is " << m.size1()
 
  737                          << 
" but the size of the first DBSlice is " << s1.size() << 
"." << 
THROW;
 
  740        if (m.size2() != 0) {
 
  742                if (mcOff(m.size2()) != att.dim[0]) {
 
  743                    DBError() << 
"Cannot read dataset " << key << 
", its second dimension is " 
  744                              << att.dim[0] << 
" instead of " << m.size2() << 
"." << 
THROW;
 
  746            } 
else if (m.size2() != s2.size()) {
 
  747                DBError() << 
"Cannot read dataset " << key
 
  748                          << 
", the second dimension of the matrix is " << m.size2()
 
  749                          << 
" but the size of the second DBSlice is " << s2.size() << 
"." << 
THROW;
 
  753        if (s1.is_all() && s2.is_all()) {
 
  754            m.resize(att.dim[1], att.dim[0]);
 
  756            m.resize(s1.is_all() ? att.dim[1] : s1.size(), s2.is_all() ? att.dim[0] : s2.size());
 
  759        void* p = (
void*)&m(0, 0);
 
  760        std::vector<char> tmp;
 
  762            tmp.resize(mcSizeof(att.type) * m.size1() * m.size2());
 
  766        if (s1.is_all() && s2.is_all()) {
 
  767            int status = mcDBgetSetArray(handler, key.c_str(), m.size1() * m.size2(), p);
 
  769                DBError() << 
"mcDBgetSetposArray returns an unexpected error: " 
  770                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  776                sl[0].end = att.dim[0];
 
  783                sl[1].end = att.dim[1];
 
  786                s1.set_mcslice(sl + 1);
 
  788            int status = mcDBgetSetsliceArray(handler, key.c_str(), 1, sl, 0, 
nullptr, p);
 
  790                DBError() << 
"mcDBgetSetsliceArray returns an unexpected error: " 
  791                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  802    template <
typename T>
 
  804          const std::string& key, b2linalg::Matrix<T, b2linalg::Mrectangle_increment_ref> m,
 
  805          const DBSlice& s1 = DBSlice::all, 
const DBSlice& s2 = DBSlice::all) {
 
  807        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  808            DBError() << 
"Cannot read dataset " << key << 
", it does not exist." << 
THROW;
 
  811            DBError() << 
"Cannot read dataset " << key << 
", it has " << att.ndim
 
  812                      << 
" instead of 2 dimensions." << 
THROW;
 
  814        bool convert = 
false;
 
  817                DBError() << 
"Cannot read dataset " << key << 
" its type is" << att.type
 
  824            if (mcOff(m.size1()) != att.dim[1]) {
 
  825                DBError() << 
"Cannot read dataset " << key << 
" its first dimension is " 
  826                          << att.dim[1] << 
" instead of " << m.size1() << 
"." << 
THROW;
 
  828        } 
else if (m.size1() != s1.size()) {
 
  829            DBError() << 
"Cannot read dataset " << key << 
", the first dimension of the matrix is " 
  830                      << m.size1() << 
" but the size of the first DBSlice is " << s1.size() << 
"." 
  834            if (mcOff(m.size2()) != att.dim[0]) {
 
  835                DBError() << 
"Cannot read dataset " << key << 
", its second dimension is " 
  836                          << att.dim[0] << 
" instead of " << m.size2() << 
"." << 
THROW;
 
  838        } 
else if (m.size2() != s2.size()) {
 
  839            DBError() << 
"Cannot read dataset " << key << 
", the second dimension of the matrix is " 
  840                      << m.size2() << 
" but the size of the second DBSlice is " << s2.size() << 
"." 
  844        void* p = (
void*)&m(0, 0);
 
  845        std::vector<char> tmp;
 
  847            tmp.resize(mcSizeof(att.type) * m.size1() * m.size2());
 
  851        if (s1.is_all() && s2.is_all()) {
 
  852            int status = mcDBgetSetArray(handler, key.c_str(), m.size1() * m.size2(), p);
 
  854                DBError() << 
"mcDBgetSetposArray returns an unexpected error: " 
  855                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  861                sl[0].end = att.dim[0];
 
  868                sl[1].end = att.dim[1];
 
  871                s1.set_mcslice(sl + 1);
 
  873            int status = mcDBgetSetsliceArray(handler, key.c_str(), 1, sl, 0, 
nullptr, p);
 
  875                DBError() << 
"mcDBgetSetsliceArray returns an unexpected error: " 
  876                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  887    template <
typename T>
 
  889          const std::string& key, 
const std::vector<T>& v, 
const DBSlice& s1 = DBSlice::all,
 
  890          bool new_set = 
false) {
 
  891        set(key, b2linalg::Vector<T, b2linalg::Vincrement_constref>(v), s1, new_set);
 
 
  895    template <
typename T>
 
  897          const std::string& key, 
const b2linalg::Vector<T, b2linalg::Vincrement_constref>& v,
 
  898          const DBSlice& s1 = DBSlice::all, 
bool new_set = 
false) {
 
  900        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  902                DBError() << 
"Cannot write dataset " << key
 
  903                          << 
" an existing dataset is requested, but the dataset " 
  907            mcOff dim = v.size();
 
  910                DBError() << 
"mcDBcreateSet returns an unexpected error: " 
  911                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  915                DBError() << 
"Cannot write dataset " << key
 
  916                          << 
", a new dataset is requested but the dataset already " 
  921                DBError() << 
"Cannot write dataset " << key << 
", its type is " << att.type
 
  925                DBError() << 
"Cannot write dataset " << key << 
", it has " << att.ndim
 
  926                          << 
" instead of 1 dimensions." << 
THROW;
 
  928            if (att.dim[0] != mcOff((s1.is_all() ? v.size() : s1.size()))) {
 
  929                DBError() << 
"Cannot write dataset " << key << 
", its first dimension is " 
  930                          << att.dim[0] << 
" instead of " << (s1.is_all() ? v.size() : s1.size())
 
  935            int status = mcDBputSet(
 
  938                DBError() << 
"mcDBputSetpos returns an unexpected error: " 
  939                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  944            int status = mcDBputSetslice(
 
  946                  const_cast<T*
>(&v[0]));
 
  948                DBError() << 
"mcDBputSetslice returns an unexpected error: " 
  949                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
  955    template <
typename T>
 
  957          const std::string& key, 
const b2linalg::Vector<T, b2linalg::Vincrement_constref>& v,
 
  960        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
  961            if (!s1.is_all() || !s2.is_all()) {
 
  962                DBError() << 
"Cannot write dataset " << key
 
  963                          << 
", an existing dataset is requested, but the dataset " 
  967            mcOff dim = v.size();
 
  970                DBError() << 
"mcDBcreateSet returns an unexpected error: " 
  971                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
  975                DBError() << 
"Cannot write dataset " << key
 
  976                          << 
", a new dataset is requested but the dataset already " 
  981                DBError() << 
"Cannot write dataset " << key << 
", its type is " << att.type
 
  986                    DBError() << 
"Cannot write dataset" << key << 
", it has " << att.ndim
 
  987                              << 
" instead of 1 dimensions." << 
THROW;
 
  991                    DBError() << 
"Cannot write dataset " << key << 
", it has " << att.ndim
 
  992                              << 
" instead of 2 dimensions." << 
THROW;
 
  994                if (att.dim[1] > s2.end) {
 
  995                    DBError() << 
"Cannot write dataset " << key << 
", its second dimension is " 
  996                              << att.dim[0] << 
" but should be less than " << s2.end << 
"." 
 1000            if (att.dim[0] != mcOff(s1.is_all() ? v.size() : s1.size())) {
 
 1001                DBError() << 
"Cannot write dataset " << key << 
", its first dimension is " 
 1002                          << att.dim[0] << 
" instead of " << (s1.is_all() ? v.size() : s1.size())
 
 1006        if (s1.is_all() && s2.is_all()) {
 
 1007            int status = mcDBputSet(
 
 1010                DBError() << 
"mcDBputSetpos returns an unexpected error: " 
 1011                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 1016            s1.set_mcslice(sl + 1);
 
 1017            int status = mcDBputSetslice(
 
 1019                  const_cast<T*
>(&v[0]));
 
 1021                DBError() << 
"mcDBputSetslice returns an unexpected error: " 
 1022                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
 1028    template <
typename T>
 
 1030          const std::string& key, 
const b2linalg::Matrix<T, b2linalg::Mrectangle>& m,
 
 1031          const DBSlice& s1 = DBSlice::all, 
const DBSlice& s2 = DBSlice::all,
 
 1032          bool new_set = 
false) {
 
 1033        set(key, b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(m), s1, s2, new_set);
 
 
 1037    template <
typename T>
 
 1039          const std::string& key, 
const b2linalg::Matrix<T, b2linalg::Mrectangle_constref>& m,
 
 1040          const DBSlice& s1 = DBSlice::all, 
const DBSlice& s2 = DBSlice::all,
 
 1041          bool new_set = 
false) {
 
 1042        mcSetAttributes att;
 
 1043        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
 1044            if (!s1.is_all() || !s2.is_all()) {
 
 1045                DBError() << 
"Cannot write dataset " << key
 
 1046                          << 
", an existing dataset is requested, but the dataset " 
 1050            mcOff dim[2] = {mcOff(m.size2()), mcOff(m.size1())};
 
 1053                DBError() << 
"mcDBcreateSet returns an unexpected error: " 
 1054                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 1058                DBError() << 
"Cannot write dataset " << key
 
 1059                          << 
", a new dataset is requested but the dataset already " 
 1064                DBError() << 
"Cannot write dataset " << key << 
", its type is " << att.type
 
 1067            if (att.ndim != 2) {
 
 1068                DBError() << 
"Cannot write dataset " << key << 
", it has " << att.ndim
 
 1069                          << 
" instead of 2 dimensions." << 
THROW;
 
 1071            if (att.dim[0] != mcOff(s1.is_all() ? m.size2() : s2.size())) {
 
 1072                DBError() << 
"Cannot write dataset " << key << 
", its first dimension is " 
 1073                          << att.dim[0] << 
" instead of " << (s1.is_all() ? m.size2() : s2.size())
 
 1076            if (att.dim[1] != mcOff(s2.is_all() ? m.size1() : s1.size())) {
 
 1077                DBError() << 
"Cannot write dataset " << key << 
" its second dimension is " 
 1078                          << att.dim[1] << 
" instead of " << (s2.is_all() ? m.size1() : s1.size())
 
 1082        if (s1.is_all() && s2.is_all()) {
 
 1083            int status = mcDBputSet(
 
 1085                  const_cast<T*
>(&m(0, 0)));
 
 1087                DBError() << 
"mcDBputSetpos returns an unexpected error: " 
 1088                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 1093            s1.set_mcslice(sl + 1);
 
 1094            int status = mcDBputSetslice(
 
 1096                  const_cast<T*
>(&m(0, 0)));
 
 1098                DBError() << 
"mcDBputSetslice returns an unexpected error: " 
 1099                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
 1105    template <
typename T>
 
 1107          const std::string& key, 
const b2linalg::Matrix<T, b2linalg::Mpacked>& m,
 
 1108          bool new_set = 
false) {
 
 1109        mcSetAttributes att;
 
 1110        if (mcDBinqSetAtt(handler, key.c_str(), &att) == 0) {
 
 1111            mcOff dim[1] = {mcOff(m.esize())};
 
 1114                DBError() << 
"mcDBcreateSet returns an unexpected error: " 
 1115                          << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 1119                DBError() << 
"Cannot write dataset " << key
 
 1120                          << 
", a new dataset is requested but the dataset already " 
 1125                DBError() << 
"Cannot write dataset " << key << 
", its type is " << att.type
 
 1128            if (att.ndim != 1) {
 
 1129                DBError() << 
"Cannot write dataset " << key << 
", it has " << att.ndim
 
 1130                          << 
" instead of 1 dimensions." << 
THROW;
 
 1132            if (att.dim[0] != mcOff(m.esize())) {
 
 1133                DBError() << 
"Cannot write dataset " << key << 
", its first dimension is " 
 1134                          << att.dim[0] << 
" instead of " << m.esize() << 
"." << 
THROW;
 
 1137        int status = mcDBputSet(
 
 1140            DBError() << 
"mcDBputSetpos returns an unexpected error: " 
 1141                      << mcErrGetMsgAndReset(status) << 
"." << 
THROW;
 
 
 1146    void get(
const std::string& key, 
RTable& rtable, 
const DBSlice& s1 = DBSlice::all) 
const;
 
 1149    void set(
const std::string& key, 
const RTable& rtable, 
bool new_set = 
false);
 
 1152    void set(
const std::string& key, 
const RTable& rtable, 
size_t pos);
 
 1156          const std::string& key, 
RTable& rtable,
 
 1157          bool raise_exception_on_missing_desc = 
true) 
const;
 
 1163    void get(
const std::string& key, ArrayRTable& rtable) 
const;
 
 1167          const std::string& key, 
const std::vector<RTable>& array_rtable, 
bool new_set = 
false,
 
 1168          bool new_sparse_table = 
false);
 
 1173        template <
typename T>
 
 1174        ArrayTableCol(
const std::string& col_name, 
const b2linalg::Matrix<T>& mat)
 
 1180              value(&mat(0, 0)) {}
 
 1182        template <
typename T>
 
 1183        ArrayTableCol(
const std::string& col_name, 
size_t col_size, 
const std::vector<T>& v)
 
 1186              nrow(v.size() / col_size),
 
 1191        template <
typename T>
 
 1193              const std::string& col_name, 
size_t col_size, 
size_t row_size, 
const T* v,
 
 1202        void init_mcATColIndBuf(
int column, mcATColIndBuf& att)
 const {
 
 1203            att.column = column + 1;
 
 1204            att.buffer = 
const_cast<void*
>(value);
 
 1205            att.buffer_step = step;
 
 1211        const char* type_name;
 
 
 1216    void set(
const std::string& key, 
const std::vector<ArrayTableCol>& cols, 
bool new_set = 
false) {
 
 1218            std::ostringstream o;
 
 1219            o << cols[0].name << 
":" << cols[0].ncol << cols[0].type_name;
 
 1220            for (
size_t i = 1; i < cols.size(); ++i) {
 
 1222                o << 
"." << cols[i].
name << 
":" << cols[i].ncol << cols[i].type_name;
 
 1224            std::string colspec = o.str();
 
 1227                    DBError() << 
"Cannot write dataset " << key
 
 1228                              << 
", a new dataset is requested but the dataset " 
 1232                    int status = mcDBdeleteSet(handler, key.c_str());
 
 1233                    if (status != 0) { 
DBError() << mcErrGetMsgAndReset(status) << 
THROW; }
 
 1236            int status = mcATcreateTable(handler, key.c_str(), cols[0].nrow, colspec.c_str());
 
 1237            if (status != 0) { 
DBError() << mcErrGetMsgAndReset(status) << 
THROW; }
 
 1240            std::vector<mcATColIndBuf> col_att(cols.size());
 
 1241            for (
size_t i = 0; i < cols.size(); ++i) { cols[i].init_mcATColIndBuf(i, col_att[i]); }
 
 1243                      handler, key.c_str(), 1, cols[0].nrow, 1, col_att.size(), &col_att[0])) {
 
 
 1251    std::string db_name;
 
 1254    bool close_db_on_delete;
 
 1259    static bool can_convert_data(
const std::string& type_from, 
const std::string& type_to) {
 
 1260        if (type_from == 
"F") {
 
 1261            if (type_to == 
"Z") { 
return true; }
 
 1263        } 
else if (type_from == 
"Z") {
 
 1264            if (type_to == 
"F") { 
return true; }
 
 1270    static void convert_data(
 
 1271          const size_t num_elements, 
const std::string& type_from, 
const std::string& type_to,
 
 1272          const void* data_from, 
void* data_to) {
 
 1273        if (type_from == 
"F") {
 
 1274            const double* data_from_t = (
const double*)data_from;
 
 1275            if (type_to == 
"Z") {
 
 1276                b2000::csda<double>* data_to_t = (b2000::csda<double>*)data_to;
 
 1277                std::copy_n(data_from_t, num_elements, data_to_t);
 
 1281        } 
else if (type_from == 
"Z") {
 
 1282            const b2000::csda<double>* data_from_t = (
const b2000::csda<double>*)data_from;
 
 1283            if (type_to == 
"F") {
 
 1284                double* data_to_t = (
double*)data_to;
 
 1285                std::copy_n(data_from_t, num_elements, data_to_t);
 
 
 1295class DataBaseFieldSet : 
public DataBase {
 
 1297    DataBaseFieldSet() : DataBase(), fields_loaded(false), fields_saved(true) {}
 
 1299    void add_field_entry(
 
 1300          const std::string& title, 
const std::string& gname, 
const std::string& type,
 
 1301          const std::string& csys, 
const bool indexed, 
const bool discrete, 
const bool additive);
 
 1303    void close()
 override {
 
 1308    void sync()
 override {
 
 1313    void temporary_close()
 override {
 
 1315        fields_loaded = 
false;
 
 1316        fields_saved = 
true;
 
 1317        fields_rtables.clear();
 
 1318        fields_indices.clear();
 
 1319        DataBase::temporary_close();
 
 1325    typedef std::map<std::string, int> FieldsIndices;
 
 1329    ArrayRTable fields_rtables;
 
 1330    FieldsIndices fields_indices;
 
 1333void remove_database(
const std::string& name, 
bool remove_directory);
 
#define THROW
Definition b2exception.H:198
 
Definition b2database.H:260
 
A column in an array table dataset.
Definition b2database.H:1171
 
The object associated with the B2000++ database.
Definition b2database.H:288
 
void set(const std::string &key, const b2linalg::Vector< T, b2linalg::Vincrement_constref > &v, const DBSlice &s1, const DBSlice &s2, bool new_set=false)
Write a positional dataset.
Definition b2database.H:956
 
void set(const std::string &key, const b2linalg::Matrix< T, b2linalg::Mpacked > &m, bool new_set=false)
Write a positional dataset.
Definition b2database.H:1106
 
void sync_delayed()
Definition b2database.H:353
 
void get(const std::string &key, b2linalg::Vector< T, b2linalg::Vincrement_ref > v, const DBSlice &s1, const DBSlice &s2)
Read a positional dataset.
Definition b2database.H:644
 
void set(const std::string &key, const std::vector< ArrayTableCol > &cols, bool new_set=false)
Write an array table dataset.
Definition b2database.H:1216
 
const std::vector< size_t > dims(const std::string &key) const
Definition b2database.H:389
 
void get(const std::string &key, std::vector< T > &v, const DBSlice &s1, const DBSlice &s2)
Read a positional dataset.
Definition b2database.H:520
 
void rename(const std::string &oldkey, const std::string &newkey)
Rename a dataset.
Definition b2database.H:439
 
int get_handle()
Definition b2database.H:320
 
void set(const std::string &key, const b2linalg::Vector< T, b2linalg::Vincrement_constref > &v, const DBSlice &s1=DBSlice::all, bool new_set=false)
Write a positional dataset.
Definition b2database.H:896
 
bool has_key(const std::string &key) const
Definition b2database.H:323
 
void get(const std::string &key, std::vector< T > &v, const DBSlice &s1=DBSlice::all) const
Read a positional dataset.
Definition b2database.H:458
 
void init(const std::string &name)
Set the name of the MemCom database directory.
Definition b2database.C:105
 
std::string get_name() const
Definition b2database.H:303
 
void set(const std::string &key, const b2linalg::Matrix< T, b2linalg::Mrectangle_constref > &m, const DBSlice &s1=DBSlice::all, const DBSlice &s2=DBSlice::all, bool new_set=false)
Write a positional dataset.
Definition b2database.H:1038
 
void remove(const std::string &key)
Remove a dataset.
Definition b2database.H:430
 
void add_keys(const std::string &pattern, SetNameSet &set_names) const
Definition b2database.H:332
 
void open(bool readonly=false)
Open the database.
Definition b2database.C:140
 
void set(const std::string &key, const b2linalg::Matrix< T, b2linalg::Mrectangle > &m, const DBSlice &s1=DBSlice::all, const DBSlice &s2=DBSlice::all, bool new_set=false)
Write a positional dataset.
Definition b2database.H:1029
 
void set(const std::string &key, const std::vector< T > &v, const DBSlice &s1=DBSlice::all, bool new_set=false)
Write a positional dataset.
Definition b2database.H:888
 
virtual void sync()
Write all pending data to the files, in particular the index.
Definition b2database.H:341
 
bool get_desc(const std::string &key, RTable &rtable, bool raise_exception_on_missing_desc=true) const
Read the dataset descriptor.
Definition b2database.C:310
 
void set_desc(const std::string &key, const RTable &rtable)
Write the dataset descriptor.
Definition b2database.C:341
 
void get(const std::string &key, b2linalg::Matrix< T, b2linalg::Mrectangle_increment_ref > m, const DBSlice &s1=DBSlice::all, const DBSlice &s2=DBSlice::all)
Read a positional dataset.
Definition b2database.H:803
 
std::set< SetName > SetNameSet
A collection of dataset names.
Definition b2database.H:328
 
void get(const std::string &key, b2linalg::Vector< T, b2linalg::Vincrement_ref > v, const DBSlice &s1=DBSlice::all)
Read a positional dataset.
Definition b2database.H:586
 
size_t ndim(const std::string &key) const
Definition b2database.H:380
 
void get(const std::string &key, b2linalg::Matrix< T, b2linalg::Mrectangle > &m, const DBSlice &s1=DBSlice::all, const DBSlice &s2=DBSlice::all)
Read a positional dataset.
Definition b2database.H:708
 
virtual void close()
Flush all pending data and close the database.
Definition b2database.H:311
 
const std::type_info & element_type(const std::string &key) const
Definition b2database.H:398
 
Definition b2exception.H:131
 
const char * name() const noexcept
Definition b2exception.H:154
 
Definition b2rtable.H:427
 
MemCom dataset names according to the B2000++ conventions.
Definition b2database.H:49
 
Definition b2logging.H:495
 
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
 
std::string join(const std::string &a, const std::string &b)
Definition b2path.C:165
 
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
 
GenericException< IOError_name > IOError
Definition b2exception.H:335
 
GenericException< DBError_name > DBError
Definition b2exception.H:340
 
Definition b2database.H:231