Belle II Software  release-08-01-10
DBObject.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include "daq/slc/database/DBObject.h"
9 
10 #include <daq/slc/base/StringUtil.h>
11 #include <daq/slc/base/Reader.h>
12 #include <daq/slc/base/Writer.h>
13 
14 #include <cstdio>
15 #include <cstdlib>
16 #include <cstring>
17 #include <sstream>
18 
19 using namespace Belle2;
20 
21 DBObject::DBObject()
22 {
23  setDate(0);
24 }
25 
26 DBObject::DBObject(const std::string& path)
27 {
28  setDate(0);
29  setPath(path);
30 }
31 
32 DBObject::DBObject(const DBObject& obj)
33  : AbstractDBObject(obj)
34 {
35  copy(obj);
36 }
37 
38 const DBObject& DBObject::operator=(const DBObject& obj)
39 {
40  copy(obj);
41  return *this;
42 }
43 
44 void DBObject::copy(const DBObject& obj)
45 {
46  reset();
47  setDate(obj.getDate());
48  setIndex(obj.getIndex());
49  setId(obj.getId());
50  setPath(obj.getPath());
51  setName(obj.getName());
52  for (DBField::NameList::const_iterator it = obj.getFieldNames().begin();
53  it != obj.getFieldNames().end(); ++it) {
54  const std::string& name(*it);
55  DBField::Type type = obj.getProperty(name).getType();
56  switch (type) {
57  case DBField::BOOL: addBool(name, obj.getBool(name)); break;
58  case DBField::CHAR: addChar(name, obj.getChar(name)); break;
59  case DBField::SHORT: addShort(name, obj.getShort(name)); break;
60  case DBField::INT: addInt(name, obj.getInt(name)); break;
61  case DBField::LONG: addLong(name, obj.getLong(name)); break;
62  case DBField::FLOAT: addFloat(name, obj.getFloat(name)); break;
63  case DBField::DOUBLE: addDouble(name, obj.getDouble(name)); break;
64  case DBField::TEXT: addText(name, obj.getText(name)); break;
65  case DBField::OBJECT: addObjects(name, obj.getObjects(name)); break;
66  default: break;
67  }
68  }
69 }
70 
71 DBObject::~DBObject()
72 {
73  reset();
74 }
75 
76 int DBObject::getNObjects(const std::string& name) const
77 {
78  FieldObjectList::const_iterator it = m_obj_v_m.find(name);
79  if (it != m_obj_v_m.end()) return it->second.size();
80  return 0;
81 }
82 
83 DBObjectList& DBObject::getObjects(const std::string& name)
84 {
85  FieldObjectList::iterator it = m_obj_v_m.find(name);
86  if (it != m_obj_v_m.end()) return it->second;
87  else throw (std::out_of_range(StringUtil::form("%s not found in %s (%s:%d)",
88  name.c_str(), getName().c_str(),
89  __FILE__, __LINE__)));
90 }
91 
92 const DBObjectList& DBObject::getObjects(const std::string& name) const
93 {
94  FieldObjectList::const_iterator it = m_obj_v_m.find(name);
95  if (it != m_obj_v_m.end()) return it->second;
96  else throw (std::out_of_range(StringUtil::form("%s not found in %s (%s:%d)",
97  name.c_str(), getName().c_str(),
98  __FILE__, __LINE__)));
99 }
100 
101 DBObject& DBObject::getObject(const std::string& name, int i)
102 {
103  FieldObjectList::iterator it = m_obj_v_m.find(name);
104  if (it != m_obj_v_m.end()) return it->second[i];
105  else throw (std::out_of_range(StringUtil::form("%s not found in %s (%s:%d)",
106  name.c_str(), getName().c_str(),
107  __FILE__, __LINE__)));
108 }
109 
110 const DBObject& DBObject::getObject(const std::string& name, int i) const
111 {
112  FieldObjectList::const_iterator it = m_obj_v_m.find(name);
113  if (it != m_obj_v_m.end()) return it->second[i];
114  else throw (std::out_of_range(StringUtil::form("%s not found in %s (%s:%d)",
115  name.c_str(), getName().c_str(),
116  __FILE__, __LINE__)));
117 }
118 
119 void DBObject::reset()
120 {
121  const DBField::NameList& name_v(getFieldNames());
122  for (size_t ii = 0; ii < name_v.size(); ii++) {
123  const std::string& name(name_v[ii]);
124  if (hasObject(name)) {
125  size_t nobj = getNObjects(name);
126  for (size_t i = 0; i < nobj; i++) getObject(name, i).reset();
127  }
128  }
129  for (FieldValueList::iterator it = m_value_m.begin();
130  it != m_value_m.end(); ++it) {
131  free(it->second);
132  }
133  m_value_m = FieldValueList();
134  m_text_m = FieldTextList();
135  m_obj_v_m = FieldObjectList();
136  AbstractDBObject::reset();
137 }
138 
139 void DBObject::readObject(Reader& reader)
140 {
141  reset();
142  setPath(reader.readString());
143  setName(reader.readString());
144  setDate(reader.readInt());
145  int npar = reader.readInt();
146  for (int i = 0; i < npar; i++) {
147  std::string name = reader.readString();
148  DBField::Type type = (DBField::Type)reader.readInt();
149  switch (type) {
150  case DBField::BOOL: addBool(name, reader.readBool()); break;
151  case DBField::CHAR: addChar(name, reader.readChar()); break;
152  case DBField::SHORT: addShort(name, reader.readShort()); break;
153  case DBField::INT: addInt(name, reader.readInt()); break;
154  case DBField::LONG: addLong(name, reader.readLong()); break;
155  case DBField::FLOAT: addFloat(name, reader.readFloat()); break;
156  case DBField::DOUBLE: addDouble(name, reader.readDouble()); break;
157  case DBField::TEXT: addText(name, reader.readString()); break;
158  case DBField::OBJECT: {
159  DBObjectList obj_v;
160  int nobj = reader.readInt();
161  for (int n = 0; n < nobj; n++) {
162  DBObject obj;
163  obj.readObject(reader);
164  obj.setIndex(n);
165  obj_v.push_back(obj);
166  }
167  addObjects(name, obj_v);
168  }; break;
169  default: break;
170  }
171  }
172 }
173 
174 void DBObject::writeObject(Writer& writer) const
175 {
176  writer.writeString(getPath());
177  writer.writeString(getName());
178  writer.writeInt(getDate());
179  const DBField::NameList& name_v(getFieldNames());
180  writer.writeInt(name_v.size());
181  for (DBField::NameList::const_iterator iname = name_v.begin();
182  iname != name_v.end(); ++iname) {
183  const std::string name = *iname;
184  DBField::Type type = getProperty(name).getType();
185  writer.writeString(name);
186  writer.writeInt(type);
187  switch (type) {
188  case DBField::BOOL: writer.writeBool(getBool(name)); break;
189  case DBField::CHAR: writer.writeChar(getChar(name)); break;
190  case DBField::SHORT: writer.writeShort(getShort(name)); break;
191  case DBField::INT: writer.writeInt(getInt(name)); break;
192  case DBField::LONG: writer.writeLong(getLong(name)); break;
193  case DBField::FLOAT: writer.writeFloat(getFloat(name)); break;
194  case DBField::DOUBLE: writer.writeDouble(getDouble(name)); break;
195  case DBField::TEXT: writer.writeString(getText(name)); break;
196  case DBField::OBJECT: {
197  const DBObjectList& obj_v(getObjects(name));
198  writer.writeInt(obj_v.size());
199  for (DBObjectList::const_iterator iobj = obj_v.begin();
200  iobj != obj_v.end(); ++iobj) {
201  iobj->writeObject(writer);
202  }
203  }; break;
204  default: break;
205  }
206  }
207 }
208 
209 const void* DBObject::getValue(const std::string& name) const
210 {
211  if (!hasValue(name)) return NULL;
212  FieldValueList::const_iterator it = m_value_m.find(name);
213  if (it != m_value_m.end()) return it->second;
214  else throw (std::out_of_range(StringUtil::form("value %s not found", name.c_str())));
215 }
216 
217 const std::string& DBObject::getText(const std::string& name) const
218 {
219  if (!hasText(name)) return m_empty;
220  FieldTextList::const_iterator it = m_text_m.find(name);
221  if (it != m_text_m.end()) return it->second;
222  else throw (std::out_of_range(StringUtil::form("text %s not found", name.c_str())));
223 }
224 
225 void DBObject::addValue(const std::string& name, const void* value,
226  DBField::Type type, int)
227 {
228  DBField::Property pro(type, 0, 0);
229  int size = pro.getTypeSize();
230  if (size <= 0) return;
231  if (!hasValue(name)) {
232  add(name, pro);
233  void* v = malloc(size);
234  memcpy(v, value, size);
235  m_value_m.insert(FieldValueList::value_type(name, v));
236  } else {
237  memcpy(m_value_m[name], value, size);
238  }
239 }
240 
241 void DBObject::setValue(const std::string& name,
242  const void* value, int)
243 {
244  const DBField::Property& pro(getProperty(name));
245  int size = pro.getTypeSize();
246  if (hasField(name) && size > 0) {
247  memcpy(m_value_m[name], value, size);
248  }
249 }
250 
251 void DBObject::addText(const std::string& name,
252  const std::string& value)
253 {
254  if (!hasField(name)) {
255  add(name, DBField::Property(DBField::TEXT, 0));
256  m_text_m.insert(FieldTextList::value_type(name, value));
257  } else {
258  m_text_m[name] = value;
259  }
260 }
261 
262 void DBObject::addObject(const std::string& name,
263  const DBObject& obj)
264 {
265  if (!hasField(name)) {
266  add(name, DBField::Property(DBField::OBJECT, 0));
267  m_obj_v_m.insert(FieldObjectList::value_type(name, DBObjectList()));
268  }
269  m_obj_v_m[name].push_back(obj);
270  getProperty(name).setLength(m_obj_v_m[name].size());
271 }
272 
273 void DBObject::addObjects(const std::string& name,
274  const DBObjectList& obj_v)
275 {
276  if (!hasField(name)) {
277  add(name, DBField::Property(DBField::OBJECT, obj_v.size()));
278  m_obj_v_m.insert(FieldObjectList::value_type(name, obj_v));
279  } else {
280  m_obj_v_m[name] = obj_v;
281  }
282 }
283 
284 void DBObject::print(bool isfull) const
285 {
286  const std::string& name_in = "";
287  NameValueList map;
288  search(map, name_in, isfull);
289  size_t length = 0;
290  for (NameValueList::iterator it = map.begin();
291  it != map.end(); ++it) {
292  if (it->name.size() > length) length = it->name.size();
293  }
294  printf("#\n");
295  printf("# DB object (confname = %s) stored at %s\n", getName().c_str(), Date(getDate()).toString());
296  printf("#\n");
297  printf("\n");
298  StringList s = StringUtil::split(getName(), '@');
299  if (s.size() > 1) {
300  printf("%*s : %s\n", int(-length), "nodename", s[0].c_str());
301  printf("%*s : %s\n", int(-length), "config", s[1].c_str());
302  } else {
303  printf("%*s : %s\n", int(-length), "config", getName().c_str());
304  }
305  printf("\n");
306  for (NameValueList::iterator it = map.begin();
307  it != map.end(); ++it) {
308  printf("%*s : %s\n", int(-length), it->name.c_str(), it->value.c_str());
309  }
310  printf("\n");
311  printf("#\n");
312  printf("#\n");
313  printf("#\n");
314 }
315 
316 const std::string DBObject::sprint(bool isfull) const
317 {
318  std::stringstream ss;
319  const std::string& name_in = "";
320  NameValueList map;
321  search(map, name_in, isfull);
322  size_t length = 0;
323  for (NameValueList::iterator it = map.begin();
324  it != map.end(); ++it) {
325  if (it->name.size() > length) length = it->name.size();
326  }
327  ss << "#" << std::endl;
328  ss << "# DB object (confname = " << getName() << ")" << std::endl;
329  ss << "#" << std::endl;
330  ss << "" << std::endl;
331  StringList s = StringUtil::split(getName(), '@');
332  if (s.size() > 1) {
333  ss << StringUtil::form("%*s : %s\n", -length, "nodename", s[0].c_str())
334  << std:: endl;
335  ss << StringUtil::form("%*s : %s\n", -length, "config", s[1].c_str())
336  << std:: endl;
337  } else {
338  ss << StringUtil::form("%*s : %s\n", -length, "config", getName().c_str())
339  << std:: endl;
340  }
341  ss << "" << std::endl;
342  for (NameValueList::iterator it = map.begin();
343  it != map.end(); ++it) {
344  ss << StringUtil::form("%*s : %s\n", -length, it->name.c_str(), it->value.c_str())
345  << std::endl;
346  }
347  ss << "" << std::endl;
348  ss << "#" << std::endl;
349  ss << "#" << std::endl;
350  ss << "#" << std::endl;
351  return ss.str();
352 }
353 
354 void DBObject::printHTML(bool isfull) const
355 {
356  const std::string& name_in = "";
357  NameValueList map;
358  search(map, name_in, isfull);
359  printf("<table>\n");
360  printf("<caption><strong>%s</strong></caption>\n", getName().c_str());
361  printf("<thead><tr><th>Name</th><th>Value</th>\n</tr></thead>\n");
362  printf("<tbody>\n");
363  StringList s = StringUtil::split(getName(), '@');
364  if (s.size() > 1) {
365  printf("<tr><td>nodename</td><td>%s</td>\n", s[0].c_str());
366  printf("<tr><td>config</td><td>%s</td>\n", s[1].c_str());
367  } else {
368  printf("<tr><td>config</td><td>%s</td>\n", getName().c_str());
369  }
370  std::string rcconfig, dbtable, nodename;
371  for (NameValueList::iterator it = map.begin();
372  it != map.end(); ++it) {
373  if (it->name.find("name") != std::string::npos) {
374  nodename = it->value;
375  printf("<tr><td>%s</td><td>%s</td>\n", it->name.c_str(), it->value.c_str());
376  } else if (it->name.find("rcconfig") != std::string::npos) {
377  rcconfig = it->value;
378  } else if (it->name.find("dbtable") != std::string::npos) {
379  dbtable = it->value;
380  printf("<tr><td>%s</td><td><a href=\"./daqconfig.php?db=%s&config=%s@%s\" >%s/%s</a></td>\n",
381  it->name.c_str(), dbtable.c_str(), nodename.c_str(), rcconfig.c_str(),
382  dbtable.c_str(), rcconfig.c_str());
383  } else {
384  printf("<tr><td>%s</td><td>%s</td>\n", it->name.c_str(), it->value.c_str());
385  }
386  }
387  printf("</tbody>\n");
388  printf("</table>\n");
389 }
390 
391 StringList DBObject::getNameList(bool isfull) const
392 {
393  const std::string& name_in = "";
394  NameValueList map;
395  search(map, name_in, isfull);
396  StringList str;
397  for (NameValueList::iterator it = map.begin();
398  it != map.end(); ++it) {
399  str.push_back(it->name);
400  }
401  return str;
402 }
403 
404 void DBObject::search(NameValueList& map, const std::string& name_in, bool isfull)
405 const
406 {
407  const DBField::NameList& name_v(getFieldNames());
408  for (DBField::NameList::const_iterator it = name_v.begin();
409  it != name_v.end(); ++it) {
410  const std::string& name(*it);
411  const DBField::Property& pro(getProperty(name));
412  std::string name_out = name_in;
413  if (name_in.size() > 0) name_out += ".";
414  name_out += name;
415  std::string ptype;
416  switch (pro.getType()) {
417  case DBField::BOOL: ptype = "bool"; break;
418  case DBField::INT: ptype = "int"; break;
419  case DBField::FLOAT: ptype = "float"; break;
420  case DBField::DOUBLE: ptype = "double"; break;
421  default : break;
422  }
423  if (pro.getType() == DBField::OBJECT) {
424  int length = getNObjects(name);
425  if (!isfull && getObject(name).getPath().size() > 0) {
426  const DBObjectList& objs(getObjects(name));
427  if (length == 1 || objs[1].getPath().size() == 0 || objs[0].getPath() == objs[1].getPath()) {
428  std::string value = objs[0].getPath();
429  value = "object(" + value + ")";
430  NameValue nv;
431  nv.name = name_out.c_str();
432  nv.value = value;
433  nv.type = pro.getType();
434  map.push_back(nv);
435  } else {
436  for (int i = 0; i < length; i++) {
437  std::string value = objs[i].getPath();
438  value = "object(" + value + ")";
439  NameValue nv;
440  nv.name = StringUtil::form("%s[%d].%s", name.c_str(), i, name_out.c_str());
441  nv.value = value;
442  nv.type = pro.getType();
443  map.push_back(nv);
444  }
445  }
446  } else {
447  size_t lengthCur = getNObjects(name);
448  if (lengthCur > 1) {
449  const DBObjectList& objs(getObjects(name));
450  for (size_t i = 0; i < lengthCur; i++) {
451  objs[i].search(map, StringUtil::form("%s[%d]", name_out.c_str(), i), isfull);
452  }
453  } else {
454  const DBObject& obj(getObject(name));
455  obj.search(map, name_out, isfull);
456  }
457  }
458  } else {
459  std::string value = getValueText(name);
460  if (ptype.size() > 0) value = ptype + "(" + value + ")";
461  NameValue nv;
462  nv.name = name_out;
463  nv.value = value;
464  nv.type = pro.getType();
465  if (pro.getType() != DBField::TEXT) {
466  nv.buf = (void*)getValue(name);
467  } else {
468  nv.buf = (void*)&getText(name);
469  }
470  map.push_back(nv);
471  }
472  }
473 }
474 
475 const std::string DBObject::printSQL(const std::string& table, int id) const
476 {
477  std::stringstream ss;
478 
479  const std::string& name_in = "";
480  NameValueList map;
481  bool isfull = false;
482  search(map, name_in, isfull);
483  for (NameValueList::iterator it = map.begin();
484  it != map.end(); ++it) {
485  NameValue& nv(*it);
486  std::string value = nv.value;
487  std::string::size_type pos = value.find_first_of("(");
488  DBField::Type type = DBField::TEXT;
489  if (pos != std::string::npos) {
490  std::string type_s = value.substr(0, pos);
491  if (type_s == "bool") type = DBField::BOOL;
492  else if (type_s == "char") type = DBField::CHAR;
493  else if (type_s == "short") type = DBField::SHORT;
494  else if (type_s == "int") type = DBField::INT;
495  else if (type_s == "float") type = DBField::FLOAT;
496  else if (type_s == "double") type = DBField::DOUBLE;
497  else if (type_s == "object") type = DBField::OBJECT;
498  if (type != DBField::TEXT) {
499  value = StringUtil::replace(value.substr(pos + 1), ")", "");
500  }
501  }
502 
503  switch (nv.type) {
504  case DBField::BOOL:
505  ss << "insert into " << table << " (pid,name,value_b) values "
506  << "(" << id << ",'" << nv.name << "'," << value << ");" << std::endl;
507  break;
508  case DBField::INT:
509  ss << "insert into " << table << " (pid,name,value_i) values "
510  << "(" << id << ",'" << nv.name << "'," << value << ");" << std::endl;
511  break;
512  case DBField::FLOAT:
513  case DBField::DOUBLE:
514  ss << "insert into " << table << " (pid,name,value_f) values "
515  << "(" << id << ",'" << nv.name << "'," << value << ");" << std::endl;
516  break;
517  case DBField::TEXT:
518  ss << "insert into " << table << " (pid,name,value_t) values "
519  << "(" << id << ",'" << nv.name << "','" << value << "');" << std::endl;
520  break;
521  default : break;
522  }
523  }
524  return ss.str();
525 }
526 
Abstract base class for different kinds of events.