8 #include "daq/slc/database/DBObjectLoader.h"
10 #include <daq/slc/system/LogFile.h>
12 #include <daq/slc/base/StringUtil.h>
13 #include <daq/slc/base/ConfigFile.h>
14 #include <daq/slc/database/DBHandlerException.h>
21 #include <daq/slc/system/LockGuard.h>
25 Mutex DBObjectLoader::m_mutex;
27 DBObject DBObjectLoader::load(
const std::string& filename)
35 const std::string nodename = config.get(
"nodename");
36 const std::string configname = config.get(
"config");
38 if (nodename.size() > 0)
39 obj.setName(nodename +
"@" + configname);
41 obj.setName(configname);
42 for (StringList::iterator it = config.getLabels().begin();
43 it != config.getLabels().end(); ++it) {
44 const std::string name = *it;
45 StringList str = StringUtil::split(name,
'.');
46 if (str[0] ==
"config")
continue;
47 if (str[0] ==
"nodename")
continue;
48 std::string value = config.get(name);
49 std::string::size_type pos = value.find_first_of(
"(");
50 DBField::Type type = DBField::TEXT;
51 if (pos != std::string::npos) {
52 std::string type_s = value.substr(0, pos);
53 if (type_s ==
"bool") type = DBField::BOOL;
54 else if (type_s ==
"int") type = DBField::INT;
55 else if (type_s ==
"float") type = DBField::FLOAT;
56 else if (type_s ==
"double") type = DBField::DOUBLE;
57 else if (type_s ==
"object") type = DBField::OBJECT;
58 if (type != DBField::TEXT) {
59 value = StringUtil::replace(value.substr(pos + 1),
")",
"");
63 if (StringUtil::tolower(value) ==
"true") {
65 }
else if (StringUtil::tolower(value) ==
"false") {
67 }
else if ((value.size() >= 2 && value.at(0) ==
'0' && value.at(1) ==
'x') ||
68 StringUtil::isdigit(value)) {
70 }
else if (StringUtil::split(value,
'.').size() < 3 &&
71 StringUtil::isdigit(StringUtil::replace(value,
".",
"")) &&
72 sscanf(value.c_str(),
"%f", &vf) == 1) {
73 type = DBField::DOUBLE;
78 if (!setObject(obj, str, type, value)) {
79 LogFile::error(
"error : %s : %s", name.c_str(), value.c_str());
86 const std::string& tablename,
87 const std::string& config_in,
bool )
89 std::string configname = config_in;
90 if (!db.isConnected()) {
94 StringList list = DBObjectLoader::getDBlist(db, tablename, configname);
95 if (list.size() == 0)
return obj;
96 StringList s = StringUtil::split(list[0],
',');
97 DBRecordList record_v;
99 ss <<
"select * from " << s[1] <<
" where pid =" << s[2] <<
" order by id";
102 db.execute(ss.str());
103 record_v = db.loadRecords();
108 if (list.size() > 0) {
110 timestamp = atoi(s[4].c_str());
113 ss <<
" config : " << configname << std::endl;
114 for (
size_t i = 0; i < record_v.size(); i++) {
116 if (record.hasField(
"value_b")) {
117 ss << record.get(
"name") <<
" : " <<
118 (record.getBool(
"value_b") ?
"true" :
"false") << std::endl;
119 }
else if (record.hasField(
"value_i")) {
120 ss << record.get(
"name") <<
" : int(" << record.get(
"value_i") <<
")" << std::endl;
121 }
else if (record.hasField(
"value_f")) {
122 ss << record.get(
"name") <<
" : double(" << record.get(
"value_f") <<
")" << std::endl;
123 }
else if (record.hasField(
"value_t")) {
124 ss << record.get(
"name") <<
" : \"" << record.get(
"value_t") <<
"\"" << std::endl;
128 obj = DBObjectLoader::load(conf);
129 obj.setDate(timestamp);
133 bool DBObjectLoader::add(
DBObject& obj, StringList& str,
134 const std::string& name_in,
const DBObject& cobj)
136 std::string name = str[0];
138 StringList sstr = StringUtil::split(str[0],
'[');
139 if (sstr.size() > 1) {
140 index = atoi(sstr[1].c_str());
146 if (str.size() > 1) {
147 str.erase(str.begin());
148 if (obj.hasObject(name)) {
149 return add(obj.getObject(name, index), str, name_in, cobj);
151 throw (std::out_of_range(StringUtil::form(
"%s:%d %s", __FILE__, __LINE__,
154 if (obj.hasObject(name) && obj.getNObjects(name) > index) {
155 obj.getObject(name, index).addObject(name_in, cobj);
158 obj.addObject(name, cobj);
161 throw (std::out_of_range(StringUtil::form(
"%s:%d %s", __FILE__, __LINE__,
162 StringUtil::join(str,
".").c_str())));
165 bool DBObjectLoader::setObject(
DBObject& obj, StringList& str,
166 DBField::Type type,
const std::string& value,
167 const std::string& table_in,
const std::string& config_in,
172 if (str.size() > 0) {
173 StringList sstr = StringUtil::split(str[0],
'[');
174 if (sstr.size() > 1) {
175 index = atoi(sstr[1].c_str());
184 if (str.size() > 1) {
185 str.erase(str.begin());
186 bool found = obj.hasObject(name);
188 DBObjectList& objs(obj.getObjects(name));
189 for (DBObjectList::iterator it = objs.begin();
190 it != objs.end(); ++it) {
191 if (it->getIndex() == index) {
201 cobj.setIndex(index);
202 obj.addObject(name, cobj);
204 DBObjectList& objs(obj.getObjects(name));
205 for (DBObjectList::iterator it = objs.begin();
206 it != objs.end(); ++it) {
208 if (cobj.getIndex() == index) {
209 return setObject(cobj, str, type, value, table_in, config_in, db);
214 case DBField::BOOL: obj.addBool(name,
false);
break;
215 case DBField::INT: obj.addInt(name, 0);
break;
216 case DBField::FLOAT: obj.addFloat(name, 0);
break;
217 case DBField::DOUBLE: obj.addDouble(name, 0);
break;
218 case DBField::TEXT: obj.addText(name, value);
break;
219 case DBField::OBJECT: {
221 std::string config_out = config_in;
224 StringList list = DBObjectLoader::getDBlist(*db, table_in, config_out);
225 if (list.size() > 0) {
228 for (
size_t i = 0; i < list.size(); i++) {
229 if (config_out == list[0]) {
235 cobj = DBObjectLoader::load(*db, table_in, config_out,
true);
237 if (list.size() > 0) {
238 config_out = list[0];
239 cobj = DBObjectLoader::load(*db, table_in, config_out,
true);
244 if (cobj.hasObject(name)) {
245 cobj.getObject(name).setPath(table_in +
"/" + config_out);
246 obj.addObjects(name, cobj.getObjects(name));
249 obj.addObject(name, cobj);
252 default :
return false;
254 obj.setValueText(name, value);
261 const std::string& tablename,
264 std::string tablename_date = tablename +
"_" +
Date().toString(
"%Y");
265 std::string tablename_id = tablename +
"_id";
267 if (!db.isConnected()) db.connect();
269 LogFile::error(e.what());
273 if (obj.getName().size() == 0) {
274 LogFile::error(
"Configname is null. createDB canceled.");
277 if (!db.checkTable(
"daqconfig")) {
278 db.execute(
"create table daqconfig \n"
279 "(name text not null, \n"
280 "id bigserial, lastupdate timestamp, \n"
282 db.execute(
"create index daqconfig_id_index on daqconfig(id);",
283 tablename.c_str(), tablename.c_str());
285 if (!db.checkTable(tablename_id)) {
287 db.execute(
"insert into daqconfig (name, lastupdate) values "
288 "('%s', current_timestamp);", tablename_id.c_str());
289 }
catch (
const std::exception& e) {
290 db.execute(
"update daqconfig set lastupdate = current_timestamp where name = '%s';",
291 tablename_id.c_str());
293 db.execute(
"create table %s \n"
294 "(name text not null \n"
295 "check (replace(name, '.', '') = name) not null, \n"
298 "record_time timestamp with time zone default current_timestamp, \n"
299 "UNIQUE (name)); ", tablename_id.c_str());
301 if (!db.checkTable(tablename_date)) {
303 db.execute(
"insert into daqconfig (name, lastupdate) values "
304 "('%s', current_timestamp);", tablename_date.c_str());
305 }
catch (
const std::exception& e) {
306 db.execute(
"update daqconfig set lastupdate = current_timestamp where name = '%s';",
307 tablename_date.c_str());
309 db.execute(
"create table %s \n"
310 "(name text not null,\n"
313 "value_b boolean default NULL, \n"
314 "value_i int default NULL, \n"
315 "value_f float default NULL, \n"
316 "value_t text default NULL \n"
317 "); ", tablename_date.c_str());
318 db.execute(
"create index %s_index on %s(id);",
319 tablename_date.c_str(), tablename_date.c_str());
322 LogFile::warning(e.what());
325 db.execute(
"begin;");
329 db.execute(
"insert into %s (name, content) values ('%s','%s') returning id;",
330 tablename_id.c_str(), obj.getName().c_str(), tablename_date.c_str());
332 DBRecordList record(db.loadRecords());
333 if (record.size() > 0) {
334 id = record[0].getInt(
"id");
337 LogFile::error(e.what());
339 db.execute(
"commit;");
340 if (failed)
return false;
341 std::string s = obj.printSQL(tablename_date,
id);
344 LogFile::error(e.what());
350 StringList DBObjectLoader::getDBlist(
DBInterface& db,
351 const std::string& tablename,
352 const std::string& grep,
int max)
356 if (!db.isConnected()) db.connect();
357 std::stringstream ss;
358 if (grep.size() > 0) {
359 const char* prefix = grep.c_str();
360 ss <<
"select id,name,content,to_char(record_time,'DD/MM HH24:MI:SS') as tdate, extract(epoch from record_time) as utime from " <<
361 tablename <<
"_id where "
362 <<
"(name like '" << prefix <<
"_%' or "
363 <<
"name like '" << prefix <<
"') order by id desc";
364 if (max > 0) ss <<
" limit " << max;
367 ss <<
"select id,name,content,to_char(record_time,'DD/MM HH24:MI:SS') as tdate, extract(epoch from record_time) as utime from " <<
368 tablename <<
"_id order by id desc";
369 if (max > 0) ss <<
" limit " << max;
373 db.execute(ss.str());
374 DBRecordList record_v(db.loadRecords());
375 for (
size_t i = 0; i < record_v.size(); i++) {
377 str.push_back(record.get(
"name") +
"," + record.get(
"content") +
"," +
378 record.get(
"id") +
"," + record.get(
"tdate") +
"," + record.get(
"utime"));
381 LogFile::error(e.what());
Lock Guard for a Mutex instance.
Abstract base class for different kinds of events.