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