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