This is Unofficial EPICS BASE Doxygen Site
pvif.h
Go to the documentation of this file.
1 #ifndef PVIF_H
2 #define PVIF_H
3 
4 #include <map>
5 
6 #include <asLib.h>
7 #include <dbAccess.h>
8 #include <dbChannel.h>
9 #include <dbStaticLib.h>
10 #include <dbLock.h>
11 #include <dbEvent.h>
12 #include <epicsVersion.h>
13 
14 #include <pv/status.h>
15 #include <pv/bitSet.h>
16 #include <pv/pvData.h>
17 #include <pv/anyscalar.h>
18 
19 #include <pv/qsrv.h>
20 
21 #ifndef VERSION_INT
22 # define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
23 #endif
24 
25 #ifndef EPICS_VERSION_INT
26 # define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
27 #endif
28 
29 #if EPICS_VERSION_INT>=VERSION_INT(3,16,0,2)
30 # define USE_MULTILOCK
31 #endif
32 
33 namespace epics {
34 namespace pvAccess {
35 class ChannelRequester;
36 }
37 }
38 
40 
41 // copy from PVField (.value sub-field) to DBF buffer
43 long copyPVD2DBF(const epics::pvData::PVField::const_shared_pointer& in,
44  void *outbuf, short outdbf, long *outnReq);
45 // copy from DBF buffer to PVField (.value sub-field)
48  const epics::pvData::PVField::shared_pointer& out,
49  epics::pvData::BitSet &changed,
51 
52 union dbrbuf {
62 
63 #ifdef EPICS_VERSION_INT
64 # if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
65  epicsInt64 dbf_INT64;
66  epicsUInt64 dbf_UINT64;
67 # endif
68 #endif
69  char dbf_STRING[MAX_STRING_SIZE];
70 };
71 
72 struct QSRV_API DBCH {
73  dbChannel *chan;
74  DBCH() :chan(0) {}
75  explicit DBCH(dbChannel *ch); // calls dbChannelOpen()
76  explicit DBCH(const std::string& name);
77  ~DBCH();
78 
79  void swap(DBCH&);
80 
81  operator dbChannel*() { return chan; }
82  operator const dbChannel*() const { return chan; }
83  dbChannel *operator->() { return chan; }
84  const dbChannel *operator->() const { return chan; }
85 private:
86  DBCH(const DBCH&);
87  DBCH& operator=(const DBCH&);
88  void prepare();
89 };
90 
91 struct ASCred {
92  // string storage must be safely mutable. cf. asAddClient()
93  std::vector<char> user, host;
94  std::vector<std::vector<char> > groups;
95  void update(const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& request);
96 };
97 
98 struct ASCLIENT {
100  std::vector<ASCLIENTPVT> grppvt;
101  ASCLIENT() :aspvt(0) {}
102  ~ASCLIENT();
103  // ASCred storage must remain valid
104  void add(dbChannel* chan, ASCred& cred);
105  bool canWrite();
106 };
107 
110  pdbRecordInfo(const char *name)
111  {
112  dbInitEntry(pdbbase, &ent);
113  if(dbFindRecordPart(&ent, &name))
114  throw std::runtime_error(ent.message);
115  }
117  {
118  dbFinishEntry(&ent);
119  }
120  const char *info(const char *key, const char *def =0)
121  {
122  if(dbFindInfo(&ent, key))
123  return def;
124  return dbGetInfoString(&ent);
125  }
126 };
127 
130  bool m_done;
132  {
133  dbInitEntry(pdbbase, &ent);
134  m_done = dbFirstRecordType(&ent)!=0;
135  while(!m_done) {
136  if(dbFirstRecord(&ent)==0)
137  break;
138  // not instances of this type
139  m_done = dbNextRecordType(&ent)!=0;
140  }
141  }
142  pdbRecordIterator(const dbChannel *chan)
143  {
144 #if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
145  dbInitEntryFromRecord(dbChannelRecord(chan), &ent);
146 #else
147  dbInitEntry(pdbbase, &ent);
148  if(dbFindRecord(&ent, dbChannelRecord(chan)->name)!=0)
149  throw std::logic_error("Record not found");
150 #endif
151  m_done = false;
152  }
153 #if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
154  pdbRecordIterator(dbCommon *prec)
155  {
156  dbInitEntryFromRecord(prec, &ent);
157  m_done = false;
158  }
159 #endif
161  {
162  dbFinishEntry(&ent);
163  }
164  bool done() const { return m_done; }
165  bool next() {
166  if(!m_done && dbNextRecord(&ent)!=0)
167  {
168  // done with this recordType
169  while(true) {
170  m_done = dbNextRecordType(&ent)!=0;
171  if(m_done) break;
172  if(dbFirstRecord(&ent)==0)
173  break;
174  // not instances of this type
175  }
176  }
177  return m_done;
178  }
179  dbCommon* record() const {
180  return m_done ? NULL : (dbCommon*)ent.precnode->precord;
181  }
182  const char *name() const {
183  return m_done ? NULL : ent.precnode->recordname;
184  }
185  const char *info(const char *key, const char *def =0)
186  {
187  if(m_done || dbFindInfo(&ent, key))
188  return def;
189  return dbGetInfoString(&ent);
190  }
191 };
192 
195  bool m_done;
197  {
198  dbCopyEntryContents(&const_cast<pdbRecordIterator&>(I).ent, &ent);
199  m_done = dbFirstInfo(&ent)!=0;
200  }
202  {
203  dbFinishEntry(&ent);
204  }
205  bool done() const { return m_done; }
206  bool next() {
207  m_done = dbNextInfo(&ent)!=0;
208  return m_done;
209  }
210  const char *name() { return dbGetInfoName(&ent); }
211  const char *value() { return dbGetInfoString(&ent); }
212 };
213 
214 struct DBEvent
215 {
216  dbEventSubscription subscript;
217  unsigned dbe_mask;
218  void *self;
219  unsigned index;
220  dbChannel *chan;
221  DBEvent() :subscript(NULL), self(NULL), index(0) {}
222  DBEvent(void* s) :subscript(NULL), self(s), index(0) {}
223  ~DBEvent() {destroy();}
224  void create(dbEventCtx ctx, dbChannel *ch, EVENTFUNC *fn, unsigned mask)
225  {
226  subscript = db_add_event(ctx, ch, fn, this, mask);
227  if(!subscript)
228  throw std::runtime_error("Failed to subscribe to dbEvent");
229  chan = ch;
230  dbe_mask = mask;
231  }
232  void destroy() {
233  if(subscript) db_cancel_event(subscript);
234  }
235  bool operator!() const { return !subscript; }
236 private:
237  DBEvent(const DBEvent&);
238  DBEvent& operator=(const DBEvent&);
239 };
240 
241 struct LocalFL
242 {
243  db_field_log *pfl;
244  bool ours;
245  LocalFL(db_field_log *pfl, dbChannel *pchan)
246  :pfl(pfl)
247  ,ours(false)
248  {
249  if(!pfl && (ellCount(&pchan->pre_chain)!=0 || ellCount(&pchan->pre_chain)==0)) {
250  pfl = db_create_read_log(pchan);
251  if(pfl) {
252  ours = true;
253  pfl = dbChannelRunPreChain(pchan, pfl);
254  if(pfl) pfl = dbChannelRunPostChain(pchan, pfl);
255  }
256  }
257  }
259  if(ours) db_delete_field_log(pfl);
260  }
261 };
262 
264 {
265  dbCommon *prec;
266  DBScanLocker(dbChannel *chan) :prec(dbChannelRecord(chan))
267  { dbScanLock(prec); }
268  DBScanLocker(dbCommon *prec) :prec(prec)
269  { dbScanLock(prec); }
271  { dbScanUnlock(prec); }
272 };
273 
274 #ifdef USE_MULTILOCK
275 
276 struct DBManyLock
277 {
278  dbLocker *plock;
279  DBManyLock() :plock(NULL) {}
280  DBManyLock(const std::vector<dbCommon*>& recs, unsigned flags=0)
281  :plock(dbLockerAlloc( (recs.size() > 0 ? (dbCommon**)&recs[0] : NULL), recs.size(), flags))
282  {
283  if(!plock) throw std::invalid_argument("Failed to create locker");
284  }
285  DBManyLock(dbCommon * const *precs, size_t nrecs, unsigned flags=0)
286  :plock(dbLockerAlloc((dbCommon**)precs, nrecs, flags))
287  {
288  if(!plock) throw std::invalid_argument("Failed to create locker");
289  }
290  ~DBManyLock() { if(plock) dbLockerFree(plock); }
291  void swap(DBManyLock& O) { std::swap(plock, O.plock); }
292  operator dbLocker*() { return plock; }
293 private:
294  DBManyLock(const DBManyLock&);
295  DBManyLock& operator=(const DBManyLock&);
296 };
297 
298 struct DBManyLocker
299 {
300  dbLocker *plock;
301  DBManyLocker(dbLocker *L) :plock(L)
302  {
303  dbScanLockMany(plock);
304  }
305  ~DBManyLocker()
306  {
307  dbScanUnlockMany(plock);
308  }
309 };
310 #endif
311 
313 {
314  struct Component {
315  std::string name;
317  Component() :index((epicsUInt32)-1) {}
318  Component(const std::string& name, epicsUInt32 index = (epicsUInt32)-1)
319  :name(name), index(index)
320  {}
321  bool isArray() const { return index!=(epicsUInt32)-1; }
322  };
323  typedef std::vector<Component> parts_t;
324  parts_t parts;
325 
327  explicit FieldName(const std::string&);
328 
329  void swap(FieldName& o) {
330  parts.swap(o.parts);
331  }
332 
333  bool empty() const { return parts.empty(); }
334  size_t size() const { return parts.size(); }
335  const Component& operator[](size_t i) const { return parts[i]; }
336  const Component& back() const { return parts.back(); }
337 
338  // Apply field name(s) to given structure
339  // if ppenclose!=NULL then the address of the enclosing field (eg. structureArray)
340  // whose fieldOffset shoulbe by used, or NULL if no enclosing
342  lookup(const epics::pvData::PVStructurePtr& S, epics::pvData::PVField** ppenclose) const;
343 
344  void show() const;
345 
346 #if !defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
347 // Workaround needed for older GCC
348 private:
349 #endif
350  // Prevent default copy/assignment op's
351  FieldName(const FieldName&);
352  FieldName& operator=(const FieldName&);
353 };
354 
355 struct QSRV_API PVIF {
356  PVIF(dbChannel *ch);
357  virtual ~PVIF() {}
358 
359  dbChannel * const chan; // borrowed reference from PVIFBuilder
360 
361  enum proc_t {
365  };
366 
369  virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl) =0;
372  virtual epics::pvData::Status get(const epics::pvData::BitSet& mask, proc_t proc=ProcInhibit, bool permit=true) =0;
374  virtual unsigned dbe(const epics::pvData::BitSet& mask) =0;
375 
376 private:
377  PVIF(const PVIF&);
378  PVIF& operator=(const PVIF&);
379 };
380 
382 
383  virtual ~PVIFBuilder() {}
384 
385  // fetch the structure description
386  virtual epics::pvData::FieldConstPtr dtype(dbChannel *channel) =0;
387 
389  const std::string& fld,
390  dbChannel *channel);
391 
392  // Attach to a structure instance.
393  // must be of the type returned by dtype().
394  // must be the root structure
395  virtual PVIF* attach(dbChannel *channel, const epics::pvData::PVStructurePtr& root, const FieldName& fld) =0;
396 
397  static PVIFBuilder* create(const std::string& name);
398 protected:
400 private:
401  PVIFBuilder(const PVIFBuilder&);
402  PVIFBuilder& operator=(const PVIFBuilder&);
403 };
404 
406 {
407  virtual ~ScalarBuilder() {}
408 
409  virtual epics::pvData::FieldConstPtr dtype(dbChannel *channel) OVERRIDE FINAL;
410  virtual PVIF* attach(dbChannel *channel, const epics::pvData::PVStructurePtr& root, const FieldName& fld) OVERRIDE FINAL;
411 };
412 
413 
414 #endif // PVIF_H
~DBEvent()
Definition: pvif.h:223
pdbRecordIterator(const dbChannel *chan)
Definition: pvif.h:142
epicsUInt16 dbf_USHORT
Definition: pvif.h:56
void dbInitEntry(dbBase *pdbbase, DBENTRY *pdbentry)
Definition: dbStaticLib.c:626
const char * dbGetInfoName(DBENTRY *pdbentry)
Definition: dbStaticLib.c:2901
long dbFirstRecordType(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1198
long dbNextInfo(DBENTRY *pdbentry)
Definition: dbStaticLib.c:2827
std::string request
const char * value()
Definition: pvif.h:211
dbEventSubscription subscript
Definition: pvif.h:216
std::tr1::shared_ptr< detail::SharedPut > put
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
bool done() const
Definition: pvif.h:205
double epicsFloat64
Definition: epicsTypes.h:49
void swap(FieldName &o)
Definition: pvif.h:329
epicsFloat32 dbf_FLOAT
Definition: pvif.h:60
void destroy()
Definition: pvif.h:232
DBEvent(void *s)
Definition: pvif.h:222
int i
Definition: scan.c:967
short PVD2DBR(epics::pvData::ScalarType pvt)
Definition: pvif.cpp:749
void * precord
Definition: dbBase.h:116
parts_t parts
Definition: pvif.h:324
const Component & operator[](size_t i) const
Definition: pvif.h:335
const char * info(const char *key, const char *def=0)
Definition: pvif.h:185
unsigned short epicsUInt16
Definition: epicsTypes.h:41
epicsEnum16 dbf_ENUM
Definition: pvif.h:57
Component(const std::string &name, epicsUInt32 index=(epicsUInt32)-1)
Definition: pvif.h:318
const char * info(const char *key, const char *def=0)
Definition: pvif.h:120
proc_t
Definition: pvif.h:361
void dbFinishEntry(DBENTRY *pdbentry)
Definition: dbStaticLib.c:632
epicsFloat64 dbf_DOUBLE
Definition: pvif.h:61
dbChannel * chan
Definition: pvif.h:73
PVIFBuilder()
Definition: pvif.h:399
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
unsigned char epicsUInt8
Definition: epicsTypes.h:39
~DBScanLocker()
Definition: pvif.h:270
DBScanLocker(dbChannel *chan)
Definition: pvif.h:266
const char * name()
Definition: pvif.h:210
#define NULL
Definition: catime.c:38
A vector of bits.
Definition: bitSet.h:56
db_field_log * pfl
Definition: pvif.h:243
bucket * lookup(char *name)
Definition: symtab.c:66
dbChannel * chan
Definition: pvif.h:220
unsigned int epicsUInt32
Definition: epicsTypes.h:43
long dbNextRecordType(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1209
dbChannel * operator->()
Definition: pvif.h:83
PVField is the base class for each PVData field.
Definition: pvData.h:152
DBCH()
Definition: pvif.h:74
long dbFindRecord(DBENTRY *pdbentry, const char *pname)
Definition: dbStaticLib.c:1559
#define OVERRIDE
Definition: pvAccess.h:55
std::tr1::shared_ptr< FieldBuilder > FieldBuilderPtr
long dbNextRecord(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1583
unsigned long long epicsUInt64
Definition: epicsTypes.h:45
long dbFindRecordPart(DBENTRY *pdbentry, const char **ppname)
Definition: dbStaticLib.c:1533
Definition: pvif.h:52
std::vector< std::vector< char > > groups
Definition: pvif.h:94
Definition: pvif.h:98
virtual ~PVIF()
Definition: pvif.h:357
bool next()
Definition: pvif.h:206
bool empty() const
Definition: pvif.h:333
Definition: pvif.h:91
float epicsFloat32
Definition: epicsTypes.h:48
virtual ~PVIFBuilder()
Definition: pvif.h:383
Definition: pvif.h:241
QSRV_API long copyDBF2PVD(const epics::pvData::shared_vector< const void > &buf, const epics::pvData::PVField::shared_pointer &out, epics::pvData::BitSet &changed, const epics::pvData::PVStringArray::const_svector &choices)
dbRecordNode * precnode
Definition: dbStaticLib.h:37
const char * dbGetInfoString(DBENTRY *pdbentry)
Definition: dbStaticLib.c:2908
epicsInt32 dbf_LONG
Definition: pvif.h:58
long dbFindInfo(DBENTRY *pdbentry, const char *name)
Definition: dbStaticLib.c:2867
~pdbRecordIterator()
Definition: pvif.h:160
void create(dbEventCtx ctx, dbChannel *ch, EVENTFUNC *fn, unsigned mask)
Definition: pvif.h:224
#define QSRV_API
Definition: qsrv.h:36
epicsUInt8 dbf_UCHAR
Definition: pvif.h:54
~pdbRecordInfo()
Definition: pvif.h:116
char epicsInt8
Definition: epicsTypes.h:38
bool ours
Definition: pvif.h:244
bool m_done
Definition: pvif.h:195
size_t size() const
Definition: pvif.h:334
std::tr1::shared_ptr< const Field > FieldConstPtr
Definition: pvIntrospect.h:137
char * message
Definition: dbStaticLib.h:40
const Component & back() const
Definition: pvif.h:336
std::vector< ASCLIENTPVT > grppvt
Definition: pvif.h:100
long dbFirstInfo(DBENTRY *pdbentry)
Definition: dbStaticLib.c:2816
Definition: pvif.h:72
epicsInt8 dbf_CHAR
Definition: pvif.h:53
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
void dbCopyEntryContents(DBENTRY *pfrom, DBENTRY *pto)
Definition: dbStaticLib.c:650
epicsUInt16 epicsEnum16
Definition: epicsTypes.h:47
unsigned dbe_mask
Definition: pvif.h:217
~pdbInfoIterator()
Definition: pvif.h:201
~LocalFL()
Definition: pvif.h:258
std::string name
Definition: pvif.h:315
const ChannelProviderRegistry::factoryfn_t fn
virtual ~ScalarBuilder()
Definition: pvif.h:407
unsigned index
Definition: pvif.h:219
#define MAX_STRING_SIZE
Definition: epicsTypes.h:65
Definition: pvif.h:214
std::tr1::shared_ptr< PVField > PVFieldPtr
Definition: pvData.h:66
epicsInt16 dbf_SHORT
Definition: pvif.h:55
Definition: pvif.h:355
void swap(shared_ptr< T > &a, shared_ptr< T > &b) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:783
long dbFirstRecord(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1569
std::vector< Component > parts_t
Definition: pvif.h:323
DBScanLocker(dbCommon *prec)
Definition: pvif.h:268
int * def
Definition: flex.c:92
DBEvent()
Definition: pvif.h:221
pdbRecordIterator()
Definition: pvif.h:131
epicsUInt32 index
Definition: pvif.h:316
QSRV_API long copyPVD2DBF(const epics::pvData::PVField::const_shared_pointer &in, void *outbuf, short outdbf, long *outnReq)
char * recordname
Definition: dbBase.h:117
ASCLIENT()
Definition: pvif.h:101
ASCLIENTPVT aspvt
Definition: pvif.h:99
std::vector< char > user
Definition: pvif.h:93
pdbRecordInfo(const char *name)
Definition: pvif.h:110
short epicsInt16
Definition: epicsTypes.h:40
bool operator!() const
Definition: pvif.h:235
int prec
Definition: reader.c:29
DBENTRY ent
Definition: pvif.h:194
dbChannel *const chan
Definition: pvif.h:359
bool next()
Definition: pvif.h:165
const char * name() const
Definition: pvif.h:182
bool isArray() const
Definition: pvif.h:321
DBENTRY ent
Definition: pvif.h:129
#define false
Definition: flexdef.h:85
const dbChannel * operator->() const
Definition: pvif.h:84
pdbInfoIterator(const pdbRecordIterator &I)
Definition: pvif.h:196
int epicsInt32
Definition: epicsTypes.h:42
#define FINAL
Definition: pvAccess.h:48
LocalFL(db_field_log *pfl, dbChannel *pchan)
Definition: pvif.h:245
epicsUInt32 dbf_ULONG
Definition: pvif.h:59
dbCommon * prec
Definition: pvif.h:265
long long epicsInt64
Definition: epicsTypes.h:44
dbCommon * record() const
Definition: pvif.h:179
DBENTRY ent
Definition: pvif.h:109
FieldName()
Definition: pvif.h:326
bool done() const
Definition: pvif.h:164