Belle II Software  release-05-02-19
NSMData.cc
1 #include "daq/slc/nsm/NSMData.h"
2 
3 #include "daq/slc/nsm/NSMCommunicator.h"
4 #include "daq/slc/nsm/NSMCallback.h"
5 #include "daq/slc/nsm/NSMHandlerException.h"
6 
7 #include <daq/slc/system/Time.h>
8 
9 #include <daq/slc/base/ConfigFile.h>
10 #include <daq/slc/base/StringUtil.h>
11 #include <daq/slc/base/Writer.h>
12 #include <daq/slc/base/Reader.h>
13 
14 #include <nsm2/belle2nsm.h>
15 extern "C" {
16 #include <nsm2/nsmlib2.h>
17 }
18 
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <unistd.h>
23 
24 using namespace Belle2;
25 
26 NSMData::NSMData(const std::string& dataname,
27  const std::string& format, int revision)
28  : AbstractDBObject(), m_allocated(false),
29  m_pdata(NULL), m_size(0), m_offset(0)
30 {
31  setName(dataname);
32  setFormat(format);
33  setRevision(revision);
34 }
35 
36 NSMData::NSMData()
37  : AbstractDBObject(), m_allocated(false),
38  m_pdata(NULL), m_size(0), m_offset(0)
39 {
40  setRevision(-1);
41 }
42 
43 NSMData::NSMData(const NSMData& data)
44  : AbstractDBObject(data)
45 {
46  m_allocated = data.m_allocated;
47  m_size = data.m_size;
48  setFormat(data.getFormat());
49  setRevision(data.getRevision());
50  setIndex(data.getIndex());
51  setName(data.getName());
52  m_pdata = NULL;
53  if (m_allocated) {
54  m_pdata = malloc(m_size);
55  memcpy(m_pdata, data.m_pdata, m_size);
56  } else {
57  if (data.m_pdata != NULL) m_pdata = data.m_pdata;
58  }
59  const DBField::NameList& name_v(data.getFieldNames());
60  for (DBField::NameList::const_iterator it = name_v.begin();
61  it != name_v.end(); it++) {
62  const std::string& name(*it);
63  const DBField::Property& pro(data.getProperty(name));
64  add(name, pro);
65  if (pro.getType() == DBField::OBJECT) {
66  NSMDataList data_v(data.getObjects(name));
67  for (size_t i = 0; i < data_v.size(); i++) {
68  NSMData& cdata(data_v[i]);
69  cdata.m_pdata = (void*)((char*)m_pdata +
70  pro.getOffset() + cdata.m_size * i);
71  }
72  m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
73  }
74  }
75 }
76 
77 NSMData::~NSMData()
78 {
79  reset();
80  if (m_allocated && m_pdata != NULL) {
81  free(m_pdata);
82  m_pdata = NULL;
83  }
84 }
85 
86 void NSMData::reset()
87 {
88  AbstractDBObject::reset();
89  if (m_allocated && m_pdata != NULL) {
90  free(m_pdata);
91  m_pdata = NULL;
92  }
93 }
94 
95 void NSMData::addValue(const std::string& name, const void* data,
96  DBField::Type type, int length)
97 {
98  DBField::Property pro(type, length, m_offset);
99  if (length == 0) length = 1;
100  int size = pro.getTypeSize() * length;
101  if (size <= 0) return;
102  if (!hasField(name)) {
103  add(name, pro);
104  m_offset += size;
105  }
106  if (data != NULL) {
107  memcpy((char*)m_pdata + pro.getOffset(), data, size);
108  }
109 }
110 
111 void NSMData::setValue(const std::string& name, const void* data,
112  int length)
113 {
114  const DBField::Property& pro(getProperty(name));
115  if (length == 0) length = 1;
116  int size = pro.getTypeSize() * length;
117  if (data != NULL && hasField(name) && size > 0) {
118  memcpy((char*)m_pdata + pro.getOffset(), data, size);
119  }
120 }
121 
122 void* NSMData::open(NSMCommunicator& com)
123 {
124  if (m_pdata == NULL) {
125  b2nsm_context(com.getContext());
126  if (getenv("NSM2_INCDIR") == NULL) {
127  ConfigFile file("slowcontrol");
128  setenv("NSM2_INCDIR", file.get("nsm.data.incpath").c_str(), 0);
129  }
130  if ((m_pdata = b2nsm_openmem(getName().c_str(), getFormat().c_str(),
131  getRevision())) == NULL) {
132  throw (NSMHandlerException("Failed to open data memory %s (%s %s %d)",
133  nsmlib_strerror(com.getContext()), getName().c_str(), getFormat().c_str(),
134  getRevision()));
135  }
136  parse();
137  }
138  return m_pdata;
139 }
140 
141 void* NSMData::allocate(NSMCommunicator& com, int interval)
142 {
143  if (m_pdata == NULL) {
144  b2nsm_context(com.getContext());
145  if (getenv("NSM2_INCDIR") == NULL) {
146  ConfigFile file("slowcontrol");
147  setenv("NSM2_INCDIR", file.get("nsm.data.incpath").c_str(), 0);
148  }
149  if ((m_pdata = b2nsm_allocmem(getName().c_str(), getFormat().c_str(),
150  getRevision(), interval)) == NULL) {
151  throw (NSMHandlerException("Failed to allocate data memory %s",
152  nsmlib_strerror(com.getContext())));
153  }
154  parse();
155  memset(m_pdata, 0, m_size);
156  m_com = &com;
157  m_tstamp = 0;
158  /*
159  com.getCallback().add(new NSMVHandlerText("nsmdata.name", true, false, getName()));
160  com.getCallback().add(new NSMVHandlerText("nsmdata.format", true, false, getFormat()));
161  com.getCallback().add(new NSMVHandlerInt("nsmdata.revision", true, false, getRevision()));
162  com.getCallback().add(new NSMVHandlerInt("nsmdata.tstamp", true, false, m_tstamp));
163  */
164  }
165  return m_pdata;
166 }
167 
168 void* NSMData::parse(const char* incpath, bool malloc_new)
169 {
170 #if NSM_PACKAGE_VERSION >= 1914
171  if (getenv("NSM2_INCDIR") == NULL) {
172  ConfigFile file("slowcontrol");
173  setenv("NSM2_INCDIR", file.get("nsm.data.incpath").c_str(), 0);
174  }
175  NSMparse* ptr = NULL;
176  char fmtstr[256];
177  int revision = 0;
178  if ((ptr = (NSMparse*)nsmlib_parsefile(getFormat().c_str(), getRevision(),
179  incpath, fmtstr, &revision)) == NULL) {
180  throw (NSMHandlerException("Failed to parse header file (%s:%d) : %s",
181  getFormat().c_str(), getRevision(), nsmlib_parseerr(NULL)));
182  }
183  if (getRevision() != revision && revision > 0) {
184  setRevision(revision);
185  }
186  int length;
187  std::string name_in;
188  parse(ptr, length, name_in);
189  if (m_size > 0 && malloc_new) {
190  m_allocated = true;
191  return (m_pdata = malloc(m_size));
192  }
193 #else
194  throw (NSMHandlerException("too old nsmlib (nsmparse) : version = %d", NSM_PACKAGE_VERSION));
195 #endif
196  return NULL;
197 }
198 
199 void NSMData::flush()
200 {
201 #if NSM_PACKAGE_VERSION >= 1914
202  m_tstamp = Time().getSecond();
203  sleep(1);
204  m_com->getCallback().set("nsmdata.tstamp", m_tstamp);
205 #endif
206 }
207 
208 #if NSM_PACKAGE_VERSION >= 1914
209 NSMparse* NSMData::parse(NSMparse* ptr, int& length, std::string& name_in)
210 {
211  m_size = 0;
212  while (ptr != NULL) {
213  length = ptr->size;
214  if (length < 0) length = 0;
215  int type = ptr->type;
216  std::string name = ptr->name;
217  int offset = ptr->offset;
218  m_offset = offset;
219  if (type == 'l') type = DBField::LONG;//INT64;
220  else if (type == 'i') type = DBField::INT;//INT32;
221  else if (type == 's') type = DBField::SHORT;//INT16;
222  else if (type == 'c') type = DBField::CHAR;//CHAR;
223  else if (type == 'L') type = DBField::LONG;//UINT64;
224  else if (type == 'I') type = DBField::INT;//UINT32;
225  else if (type == 'S') type = DBField::SHORT;//UINT16;
226  else if (type == 'C') type = DBField::CHAR;//BYTE8;
227  else if (type == 'd') type = DBField::DOUBLE;
228  else if (type == 'f') type = DBField::FLOAT;
229  else if (type == '(') {
230  NSMData data(getName(), getFormat() + "." + name, getRevision());
231  char* pdata = ((char*)m_pdata + offset);
232  data.m_pdata = pdata;
233  ptr = data.parse(ptr->next, length, name);
234  data.setFormat(getFormat() + "." + name);
235  int len = (length == 0) ? 1 : length;
236  NSMDataList data_v;
237  for (int i = 0; i < len; i++) {
238  data.setIndex(i);
239  data.m_pdata = (void*)(pdata + i * data.getSize());
240  data_v.push_back(data);
241  }
242  m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
243  type = DBField::OBJECT;
244  m_size += data.m_size * length;
245  } else if (type == ')') {
246  name_in = name;
247  return ptr;
248  }
249  DBField::Property pro((DBField::Type)type, length, offset);
250  add(name, pro);
251  int len = (length == 0) ? 1 : length;
252  m_size += pro.getTypeSize() * len;
253  if (ptr == NULL) break;
254  ptr = ptr->next;
255  }
256  return 0;
257 }
258 #endif
259 
260 void* NSMData::getValue(const std::string& name)
261 {
262  if (!hasValue(name)) return NULL;
263  char* data = (char*)get();
264  return (data + getProperty(name).getOffset());
265 }
266 
267 const void* NSMData::getValue(const std::string& name)
268 const
269 {
270  if (!hasValue(name)) return NULL;
271  char* data = (char*)get();
272  return (data + getProperty(name).getOffset());
273 }
274 
275 void NSMData::readObject(Reader& reader)
276 {
277  setName(reader.readString());
278  setFormat(reader.readString());
279  setRevision(reader.readInt());
280  int size = reader.readInt();
281  if (m_size > 0 && m_size < size) {
282  m_allocated = true;
283  free(m_pdata);
284  m_pdata = malloc(size);
285  }
286  setSize(size);
287  int npars = reader.readInt();
288  for (int n = 0; n < npars; n++) {
289  std::string name = reader.readString();
290  DBField::Type type = (DBField::Type)reader.readInt();
291  size_t length = reader.readInt();
292  size_t offset = reader.readInt();
293  if (!hasValue(name)) add(name, DBField::Property(type, length, offset));
294  void* buf = getValue(name);
295  if (length == 0) length = 1;
296  if (type == DBField::OBJECT) {
297  NSMDataList data_v;
298  for (size_t i = 0; i < length; i++) {
299  NSMData data;
300  data.m_pdata = (char*)getValue(name) + length * i;
301  reader.readObject(data);
302  data_v.push_back(data);
303  }
304  m_data_v_m.insert(NSMDataListMap::value_type(name, data_v));
305  } else {
306  for (size_t i = 0; i < length; i++) {
307  switch (type) {
308  case DBField::CHAR: ((char*)buf)[i] = reader.readChar(); break;
309  case DBField::SHORT: ((int16*)buf)[i] = reader.readShort(); break;
310  case DBField::INT: ((int32*)buf)[i] = reader.readInt(); break;
311  case DBField::LONG: ((int64*)buf)[i] = reader.readLong(); break;
312  case DBField::FLOAT: ((float*)buf)[i] = reader.readFloat(); break;
313  case DBField::DOUBLE: ((double*)buf)[i] = reader.readDouble(); break;
314  default: break;
315  }
316  }
317  }
318  }
319 }
320 
321 void NSMData::writeObject(Writer& writer) const
322 {
323  writer.writeString(getName());
324  writer.writeString(getFormat());
325  writer.writeInt(getRevision());
326  writer.writeInt(getSize());
327  const DBField::NameList& name_v(getFieldNames());
328  writer.writeInt(name_v.size());
329  for (DBField::NameList::const_iterator it = name_v.begin();
330  it != name_v.end(); it++) {
331  const std::string& name(*it);
332  writer.writeString(name);
333  const DBField::Property& pro(getProperty(name));
334  writer.writeInt(pro.getType());
335  writer.writeInt(pro.getLength());
336  writer.writeInt(pro.getOffset());
337  size_t length = pro.getLength();
338  const void* buf = getValue(name);
339  if (length == 0) length = 1;
340  if (pro.getType() == DBField::OBJECT) {
341  const NSMDataList& data_v(getObjects(name));
342  for (size_t i = 0; i < length; i++) {
343  writer.writeObject(data_v[i]);
344  }
345  } else {
346  for (size_t i = 0; i < length; i++) {
347  switch (pro.getType()) {
348  case DBField::CHAR: writer.writeChar(((char*)buf)[i]); break;
349  case DBField::SHORT: writer.writeShort(((int16*)buf)[i]); break;
350  case DBField::INT: writer.writeInt(((int64*)buf)[i]); break;
351  case DBField::LONG: writer.writeLong(((int32*)buf)[i]); break;
352  case DBField::FLOAT: writer.writeFloat(((float*)buf)[i]); break;
353  case DBField::DOUBLE: writer.writeDouble(((double*)buf)[i]); break;
354  default : break;
355  }
356  }
357  }
358  }
359 }
360 
361 void NSMData::print(const std::string& name_in) const
362 {
363  NameValueList map;
364  search(map, name_in);
365  size_t length = 0;
366  for (NameValueList::iterator it = map.begin();
367  it != map.end(); it++) {
368  if (it->name.size() > length) length = it->name.size();
369  }
370  for (NameValueList::iterator it = map.begin();
371  it != map.end(); it++) {
372  printf(StringUtil::form("%%-%ds : %%s\n", length).c_str(),
373  it->name.c_str(), it->value.c_str());
374  }
375 }
376 
377 void NSMData::search(NSMData::NameValueList& map,
378  const std::string& name_in) const
379 {
380  const DBField::NameList& name_v(getFieldNames());
381  for (DBField::NameList::const_iterator it = name_v.begin();
382  it != name_v.end(); it++) {
383  const std::string& name(*it);
384  const DBField::Property& pro(getProperty(name));
385  size_t length = pro.getLength();
386  std::string name_out = name_in;
387  if (name_in.size() > 0) name_out += ".";
388  name_out += name;
389  std::string pvtype;
390  if (length > 0) {
391  if (pro.getType() == DBField::OBJECT) {
392  const NSMDataList& data_v(getObjects(name));
393  for (size_t i = 0; i < length; i++) {
394  data_v[i].search(map, StringUtil::form("%s[%d]", name_out.c_str(), i));
395  }
396  } else {
397  const void* buf = getValue(name);
398  if (pro.getType() == DBField::CHAR) {
399  NameValue nv;
400  nv.name = name_out;
401  nv.value = (char*)buf;
402  map.push_back(nv);
403  } else {
404  const char* name_c = name_out.c_str();
405  for (int i = 0; i < (int)length; i++) {
406  std::string vname = StringUtil::form("%s[%d]", name_c, i);
407  std::string val;
408  switch (pro.getType()) {
409  case DBField::SHORT:
410  val = StringUtil::form("%d", ((int16*)buf)[i]); break;
411  case DBField::INT:
412  val = StringUtil::form("%d", ((int32*)buf)[i]); break;
413  case DBField::LONG:
414  val = StringUtil::form("%ld", ((int64*)buf)[i]); break;
415  case DBField::FLOAT:
416  val = StringUtil::form("%f", ((float*)buf)[i]); break;
417  case DBField::DOUBLE:
418  val = StringUtil::form("%d", ((double*)buf)[i]); break;
419  default : break;
420  }
421  NameValue nv;
422  nv.name = vname;
423  nv.value = val;
424  map.push_back(nv);
425  }
426  }
427  }
428  } else {
429  if (pro.getType() == DBField::OBJECT) {
430  const NSMDataList& data_v(getObjects(name));
431  data_v[0].search(map, name_out);
432  } else {
433  NameValue nv;
434  nv.name = name_out;
435  nv.value = getValueText(name);
436  map.push_back(nv);
437  }
438  }
439  }
440 }
441 
442 void NSMData::printPV(const std::string& name_in) const
443 {
444  const DBField::NameList& name_v(getFieldNames());
445  for (DBField::NameList::const_iterator it = name_v.begin();
446  it != name_v.end(); it++) {
447  const std::string& name(*it);
448  const DBField::Property& pro(getProperty(name));
449  size_t length = pro.getLength();
450  std::string name_out = name_in;
451  if (name_in.size() > 0) name_out += ":";
452  else {
453  name_out += (getName() + ":") + (getFormat() + ":");
454  }
455  name_out += name;
456  std::string pvtype;
457  switch (pro.getType()) {
458  case DBField::CHAR:
459  case DBField::SHORT:
460  case DBField::INT:
461  case DBField::LONG: pvtype = "longin"; break;
462  case DBField::FLOAT:
463  case DBField::DOUBLE: pvtype = "ai"; break;
464  default : break;
465  }
466  if (length > 0) {
467  if (pro.getType() == DBField::OBJECT) {
468  const NSMDataList& data_v(getObjects(name));
469  for (size_t i = 0; i < length; i++) {
470  data_v[i].printPV(StringUtil::form("%s[%d]", name_out.c_str(), i));
471  }
472  } else {
473  for (size_t i = 0; i < length; i++) {
474  printf("record(%s, \"B2_nsm:%s[%d]\")\n"
475  "{\n"
476  " field(SCAN, \".1 second\")\n"
477  " field(DTYP, \"nsm2_data_%s\")\n"
478  "}\n\n", pvtype.c_str(), name_out.c_str(), (int)i, pvtype.c_str());
479  }
480  }
481  } else {
482  if (pro.getType() == DBField::OBJECT) {
483  const NSMDataList& data_v(getObjects(name));
484  data_v[0].print(name_out);
485  } else {
486  printf("record(%s, \"B2_nsm2:%s\")\n"
487  "{\n"
488  " field(SCAN, \".1 second\")\n"
489  " field(DTYP, \"nsm2_data_%s\")\n"
490  "}\n\n", pvtype.c_str(), name_out.c_str(), pvtype.c_str());
491  }
492  }
493  }
494 }
495 
496 const void* NSMData::find(const std::string& name_in, DBField::Type& type, int& length) const
497 {
498  size_t pos;
499  std::string name_out = name_in;
500  if ((pos = name_in.find(".")) != std::string::npos) {
501  StringList str = StringUtil::split(name_out, '.');
502  StringList sstr = StringUtil::split(str[0], '[');
503  const NSMDataList& data_v(getObjects(sstr[0]));
504  int index = 0;
505  if (sstr.size() > 1) {
506  index = atoi(sstr[1].c_str());
507  }
508  name_out = name_in.substr(pos + 1);
509  return data_v[index].find(name_out, type, length);
510  }
511  int index = 0;
512  if ((pos = name_out.find("[")) != std::string::npos) {
513  StringList str = StringUtil::split(name_out, '[');
514  name_out = str[0];
515  index = atoi(str[1].c_str());
516  }
517  if (!hasValue(name_out)) return NULL;
518  const DBField::Property& pro(getProperty(name_out));
519  length = pro.getLength();
520  type = pro.getType();
521  const void* buf = getValue(name_out);
522  switch (type) {
523  case DBField::CHAR: return (((const char*)buf) + index);
524  case DBField::SHORT: return (((const int16*)buf) + index);
525  case DBField::INT: return (((const int32*)buf) + index);
526  case DBField::LONG: return (((const int64*)buf) + index);
527  case DBField::FLOAT: return (((const float*)buf) + index);
528  case DBField::DOUBLE: return (((const double*)buf) + index);
529  default: return NULL;
530  }
531  return NULL;
532 }
533 
534 int NSMData::getNObjects(const std::string& name) const
535 {
536  NSMDataListMap::const_iterator it = m_data_v_m.find(name);
537  if (it != m_data_v_m.end()) return it->second.size();
538  return 0;
539 }
540 
541 const NSMData& NSMData::getObject(const std::string& name, int index) const
542 {
543  NSMDataListMap::const_iterator it = m_data_v_m.find(name);
544  if (it != m_data_v_m.end()) return it->second[index];
545  else throw (std::out_of_range(StringUtil::form("%s:%d", __FILE__, __LINE__)));
546 }
547 
548 NSMData& NSMData::getObject(const std::string& name, int index)
549 {
550  NSMDataListMap::iterator it = m_data_v_m.find(name);
551  if (it != m_data_v_m.end()) return it->second[index];
552  else throw (std::out_of_range(StringUtil::form("%s:%d", __FILE__, __LINE__)));
553 }
554 
555 const NSMData::NSMDataList& NSMData::getObjects(const std::string& name) const
556 {
557  NSMDataListMap::const_iterator it = m_data_v_m.find(name);
558  if (it != m_data_v_m.end()) return it->second;
559  else throw (std::out_of_range(StringUtil::form("%s:%d", __FILE__, __LINE__)));
560 }
561 
562 NSMData::NSMDataList& NSMData::getObjects(const std::string& name)
563 {
564  NSMDataListMap::iterator it = m_data_v_m.find(name);
565  if (it != m_data_v_m.end()) return it->second;
566  else throw (std::out_of_range(StringUtil::form("%s:%d", __FILE__, __LINE__)));
567 }
568 
Belle2::Reader
Definition: Reader.h:15
Belle2::NSMData
Definition: NSMData.h:24
Belle2::NSMCommunicator
Definition: NSMCommunicator.h:25
Belle2::Writer
Definition: Writer.h:15
NSMparse_struct
Definition: nsmparse.h:13
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::NSMHandlerException
Definition: NSMHandlerException.h:12
Belle2::Time
Definition: Time.h:14
Belle2::ConfigFile
Definition: ConfigFile.h:15