9#include <dbStaticLib.h>
12#include <epicsVersion.h>
17#include <pv/anyscalar.h>
22# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
25#ifndef EPICS_VERSION_INT
26# define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
29#if EPICS_VERSION_INT>=VERSION_INT(3,16,0,2)
44class ChannelRequester;
48short PVD2DBR(epics::pvData::ScalarType pvt);
52long copyPVD2DBF(
const epics::pvData::PVField::const_shared_pointer& in,
53 void *outbuf,
short outdbf,
long *outnReq);
56long copyDBF2PVD(
const epics::pvData::shared_vector<const void>& buf,
57 const epics::pvData::PVField::shared_pointer& out,
58 epics::pvData::BitSet &changed,
59 const epics::pvData::PVStringArray::const_svector& choices);
65 epicsUInt16 dbf_USHORT;
68 epicsUInt32 dbf_ULONG;
69 epicsFloat32 dbf_FLOAT;
70 epicsFloat64 dbf_DOUBLE;
72#ifdef EPICS_VERSION_INT
73# if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
75 epicsUInt64 dbf_UINT64;
78 char dbf_STRING[MAX_STRING_SIZE];
84 explicit DBCH(dbChannel *ch);
85 explicit DBCH(
const std::string& name);
90 operator dbChannel*() {
return chan; }
91 operator const dbChannel*()
const {
return chan; }
92 dbChannel *operator->() {
return chan; }
93 const dbChannel *operator->()
const {
return chan; }
96 DBCH& operator=(
const DBCH&);
102 std::vector<char> user, host;
103 std::vector<std::vector<char> > groups;
104 void update(
const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& request);
109 std::vector<ASCLIENTPVT> grppvt;
110 ASCLIENT() :aspvt(0) {}
113 void add(dbChannel* chan,
ASCred& cred);
117struct pdbRecordInfo {
119 pdbRecordInfo(
const char *name)
121 dbInitEntry(pdbbase, &ent);
122 if(dbFindRecordPart(&ent, &name))
123 throw std::runtime_error(ent.message);
129 const char *info(
const char *key,
const char *def =0)
131 if(dbFindInfo(&ent, key))
133 return dbGetInfoString(&ent);
137struct pdbRecordIterator {
142 dbInitEntry(pdbbase, &ent);
143 m_done = dbFirstRecordType(&ent)!=0;
145 if(dbFirstRecord(&ent)==0)
148 m_done = dbNextRecordType(&ent)!=0;
151 pdbRecordIterator(
const dbChannel *chan)
153#if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
154 dbInitEntryFromRecord(dbChannelRecord(chan), &ent);
156 dbInitEntry(pdbbase, &ent);
157 if(dbFindRecord(&ent, dbChannelRecord(chan)->name)!=0)
158 throw std::logic_error(
"Record not found");
162#if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
163 pdbRecordIterator(dbCommon *prec)
165 dbInitEntryFromRecord(prec, &ent);
173 bool done()
const {
return m_done; }
175 if(!m_done && dbNextRecord(&ent)!=0)
179 m_done = dbNextRecordType(&ent)!=0;
181 if(dbFirstRecord(&ent)==0)
188 dbCommon* record()
const {
189 return m_done ? NULL : (dbCommon*)ent.precnode->precord;
191 const char *name()
const {
192 return m_done ? NULL : ent.precnode->recordname;
194 const char *info(
const char *key,
const char *def =0)
196 if(m_done || dbFindInfo(&ent, key))
198 return dbGetInfoString(&ent);
202struct pdbInfoIterator {
208 m_done = dbFirstInfo(&ent)!=0;
214 bool done()
const {
return m_done; }
216 m_done = dbNextInfo(&ent)!=0;
219 const char *name() {
return dbGetInfoName(&ent); }
220 const char *value() {
return dbGetInfoString(&ent); }
225 dbEventSubscription subscript;
230 DBEvent() :subscript(NULL), self(NULL), index(0) {}
231 DBEvent(
void* s) :subscript(NULL), self(s), index(0) {}
232 ~DBEvent() {destroy();}
233 void create(dbEventCtx ctx, dbChannel *ch, EVENTFUNC *fn,
unsigned mask)
235 subscript = db_add_event(ctx, ch, fn,
this, mask);
237 throw std::runtime_error(
"Failed to subscribe to dbEvent");
242 if(subscript) db_cancel_event(subscript);
244 bool operator!()
const {
return !subscript; }
246 DBEvent(
const DBEvent&);
247 DBEvent& operator=(
const DBEvent&);
254 LocalFL(db_field_log *pfl, dbChannel *pchan)
258 if(!pfl && (ellCount(&pchan->pre_chain)!=0 || ellCount(&pchan->post_chain)!=0)) {
259 pfl = db_create_read_log(pchan);
262 pfl = dbChannelRunPreChain(pchan, pfl);
263 if(pfl) pfl = dbChannelRunPostChain(pchan, pfl);
269 if(ours) db_delete_field_log(pfl);
276 DBScanLocker(dbChannel *chan) :prec(dbChannelRecord(chan))
277 { dbScanLock(prec); }
278 DBScanLocker(dbCommon *prec) :prec(prec)
279 { dbScanLock(prec); }
281 { dbScanUnlock(prec); }
289 DBManyLock() :plock(NULL) {}
290 DBManyLock(
const std::vector<dbCommon*>& recs,
unsigned flags=0)
291 :plock(dbLockerAlloc( (recs.size() > 0 ? (dbCommon**)&recs[0] : NULL), recs.size(), flags))
293 if(!plock)
throw std::invalid_argument(
"Failed to create locker");
295 DBManyLock(dbCommon *
const *precs,
size_t nrecs,
unsigned flags=0)
296 :plock(dbLockerAlloc((dbCommon**)precs, nrecs, flags))
298 if(!plock)
throw std::invalid_argument(
"Failed to create locker");
300 ~DBManyLock() {
if(plock) dbLockerFree(plock); }
301 void swap(DBManyLock& O) { std::swap(plock, O.plock); }
302 operator dbLocker*() {
return plock; }
304 DBManyLock(
const DBManyLock&);
305 DBManyLock& operator=(
const DBManyLock&);
311 DBManyLocker(dbLocker *L) :plock(L)
313 dbScanLockMany(plock);
317 dbScanUnlockMany(plock);
322struct QSRV_API FieldName
327 Component() :index((epicsUInt32)-1) {}
328 Component(
const std::string& name, epicsUInt32 index = (epicsUInt32)-1)
329 :name(name), index(index)
331 bool isArray()
const {
return index!=(epicsUInt32)-1; }
333 typedef std::vector<Component> parts_t;
343 bool empty()
const {
return parts.empty(); }
344 size_t size()
const {
return parts.size(); }
345 const Component& operator[](
size_t i)
const {
return parts[i]; }
346 const Component& back()
const {
return parts.back(); }
351 epics::pvData::PVFieldPtr
352 lookup(
const epics::pvData::PVStructurePtr& S, epics::pvData::PVField** ppenclose)
const;
356#if !defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
361 FieldName(
const FieldName&);
362 FieldName& operator=(
const FieldName&);
365struct QSRV_API PVIF {
369 dbChannel *
const chan;
379 virtual void put(epics::pvData::BitSet& mask,
unsigned dbe, db_field_log *pfl) =0;
382 virtual epics::pvData::Status
get(
const epics::pvData::BitSet& mask, proc_t proc=ProcInhibit,
bool permit=
true) =0;
384 virtual unsigned dbe(
const epics::pvData::BitSet& mask) =0;
388 PVIF& operator=(
const PVIF&);
403struct QSRV_API PVIFBuilder
405 dbChannel*
const channel;
407 virtual ~PVIFBuilder() {}
410 virtual epics::pvData::FieldConstPtr dtype() =0;
412 virtual epics::pvData::FieldBuilderPtr dtype(epics::pvData::FieldBuilderPtr& builder,
413 const std::string& fld);
418 virtual PVIF* attach(
const epics::pvData::PVStructurePtr& root,
const FieldName& fld) =0;
421 static PVIFBuilder* create(
const std::string& mapname, dbChannel* chan);
423 explicit PVIFBuilder(dbChannel* chan) : channel(chan) {}
425 PVIFBuilder(
const PVIFBuilder&);
426 PVIFBuilder& operator=(
const PVIFBuilder&);
429struct QSRV_API ScalarBuilder :
public PVIFBuilder
431 explicit ScalarBuilder(dbChannel* chan) :PVIFBuilder(chan) {}
432 virtual ~ScalarBuilder() {}
434 virtual epics::pvData::FieldConstPtr dtype() OVERRIDE FINAL;
435 virtual PVIF* attach(
const epics::pvData::PVStructurePtr& root,
const FieldName& fld) OVERRIDE FINAL;
virtual void put(epics::pvData::BitSet &mask, unsigned dbe, db_field_log *pfl)=0
virtual unsigned dbe(const epics::pvData::BitSet &mask)=0
Calculate DBE mask from changed bitset.
virtual epics::pvData::Status get(const epics::pvData::BitSet &mask, proc_t proc=ProcInhibit, bool permit=true)=0