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