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>
25Mutex DBObjectLoader::m_mutex;
27DBObject 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);
133bool DBObjectLoader::add(
DBObject& obj, StringList& str,
134 const std::string& name_in,
const DBObject& cobj)
138 StringList sstr = StringUtil::split(str[0],
'[');
139 if (sstr.size() > 1) {
140 index = atoi(sstr[1].c_str());
147 if (str.size() > 1) {
148 str.erase(str.begin());
149 if (obj.hasObject(name)) {
150 return add(obj.getObject(name, index), str, name_in, cobj);
152 throw (std::out_of_range(StringUtil::form(
"%s:%d %s", __FILE__, __LINE__,
155 if (obj.hasObject(name) && obj.getNObjects(name) > index) {
156 obj.getObject(name, index).addObject(name_in, cobj);
159 obj.addObject(name, cobj);
162 throw (std::out_of_range(StringUtil::form(
"%s:%d %s", __FILE__, __LINE__,
163 StringUtil::join(str,
".").c_str())));
166bool DBObjectLoader::setObject(
DBObject& obj, StringList& str,
167 DBField::Type type,
const std::string& value,
168 const std::string& table_in,
const std::string& config_in,
173 if (str.size() > 0) {
174 StringList sstr = StringUtil::split(str[0],
'[');
175 if (sstr.size() > 1) {
176 index = atoi(sstr[1].c_str());
185 if (str.size() > 1) {
186 str.erase(str.begin());
187 bool found = obj.hasObject(name);
189 DBObjectList& objs(obj.getObjects(name));
190 for (DBObjectList::iterator it = objs.begin();
191 it != objs.end(); ++it) {
192 if (it->getIndex() == index) {
202 cobj.setIndex(index);
203 obj.addObject(name, cobj);
205 DBObjectList& objs(obj.getObjects(name));
206 for (DBObjectList::iterator it = objs.begin();
207 it != objs.end(); ++it) {
209 if (cobj.getIndex() == index) {
210 return setObject(cobj, str, type, value, table_in, config_in, db);
215 case DBField::BOOL: obj.addBool(name,
false);
break;
216 case DBField::INT: obj.addInt(name, 0);
break;
217 case DBField::FLOAT: obj.addFloat(name, 0);
break;
218 case DBField::DOUBLE: obj.addDouble(name, 0);
break;
219 case DBField::TEXT: obj.addText(name, value);
break;
220 case DBField::OBJECT: {
222 std::string config_out = config_in;
225 StringList list = DBObjectLoader::getDBlist(*db, table_in, config_out);
226 if (list.size() > 0) {
229 for (
size_t i = 0; i < list.size(); i++) {
230 if (config_out == list[0]) {
236 cobj = DBObjectLoader::load(*db, table_in, config_out,
true);
238 if (list.size() > 0) {
239 config_out = list[0];
240 cobj = DBObjectLoader::load(*db, table_in, config_out,
true);
245 if (cobj.hasObject(name)) {
246 cobj.getObject(name).setPath(table_in +
"/" + config_out);
247 obj.addObjects(name, cobj.getObjects(name));
250 obj.addObject(name, cobj);
253 default :
return false;
255 obj.setValueText(name, value);
262 const std::string& tablename,
265 std::string tablename_date = tablename +
"_" +
Date().toString(
"%Y");
266 std::string tablename_id = tablename +
"_id";
268 if (!db.isConnected()) db.connect();
270 LogFile::error(e.what());
274 if (obj.getName().size() == 0) {
275 LogFile::error(
"Configname is null. createDB canceled.");
278 if (!db.checkTable(
"daqconfig")) {
279 db.execute(
"create table daqconfig \n"
280 "(name text not null, \n"
281 "id bigserial, lastupdate timestamp, \n"
283 db.execute(
"create index daqconfig_id_index on daqconfig(id);",
284 tablename.c_str(), tablename.c_str());
286 if (!db.checkTable(tablename_id)) {
288 db.execute(
"insert into daqconfig (name, lastupdate) values "
289 "('%s', current_timestamp);", tablename_id.c_str());
290 }
catch (
const std::exception& e) {
291 db.execute(
"update daqconfig set lastupdate = current_timestamp where name = '%s';",
292 tablename_id.c_str());
294 db.execute(
"create table %s \n"
295 "(name text not null \n"
296 "check (replace(name, '.', '') = name) not null, \n"
299 "record_time timestamp with time zone default current_timestamp, \n"
300 "UNIQUE (name)); ", tablename_id.c_str());
302 if (!db.checkTable(tablename_date)) {
304 db.execute(
"insert into daqconfig (name, lastupdate) values "
305 "('%s', current_timestamp);", tablename_date.c_str());
306 }
catch (
const std::exception& e) {
307 db.execute(
"update daqconfig set lastupdate = current_timestamp where name = '%s';",
308 tablename_date.c_str());
310 db.execute(
"create table %s \n"
311 "(name text not null,\n"
314 "value_b boolean default NULL, \n"
315 "value_i int default NULL, \n"
316 "value_f float default NULL, \n"
317 "value_t text default NULL \n"
318 "); ", tablename_date.c_str());
319 db.execute(
"create index %s_index on %s(id);",
320 tablename_date.c_str(), tablename_date.c_str());
323 LogFile::warning(e.what());
326 db.execute(
"begin;");
330 db.execute(
"insert into %s (name, content) values ('%s','%s') returning id;",
331 tablename_id.c_str(), obj.getName().c_str(), tablename_date.c_str());
333 DBRecordList record(db.loadRecords());
334 if (record.size() > 0) {
335 id = record[0].getInt(
"id");
338 LogFile::error(e.what());
340 db.execute(
"commit;");
341 if (failed)
return false;
342 std::string s = obj.printSQL(tablename_date,
id);
345 LogFile::error(e.what());
351StringList DBObjectLoader::getDBlist(
DBInterface& db,
352 const std::string& tablename,
353 const std::string& grep,
int max)
357 if (!db.isConnected()) db.connect();
358 std::stringstream ss;
359 if (grep.size() > 0) {
360 const char* prefix = grep.c_str();
361 ss <<
"select id,name,content,to_char(record_time,'DD/MM HH24:MI:SS') as tdate, extract(epoch from record_time) as utime from " <<
362 tablename <<
"_id where "
363 <<
"(name like '" << prefix <<
"_%' or "
364 <<
"name like '" << prefix <<
"') order by id desc";
365 if (max > 0) ss <<
" limit " << max;
368 ss <<
"select id,name,content,to_char(record_time,'DD/MM HH24:MI:SS') as tdate, extract(epoch from record_time) as utime from " <<
369 tablename <<
"_id order by id desc";
370 if (max > 0) ss <<
" limit " << max;
374 db.execute(ss.str());
375 DBRecordList record_v(db.loadRecords());
376 for (
size_t i = 0; i < record_v.size(); i++) {
378 str.push_back(record.get(
"name") +
"," + record.get(
"content") +
"," +
379 record.get(
"id") +
"," + record.get(
"tdate") +
"," + record.get(
"utime"));
382 LogFile::error(e.what());
Lock Guard for a Mutex instance.
Abstract base class for different kinds of events.