16 #define TRY pvaLink *self = static_cast<pvaLink*>(plink->value.json.jlink); assert(self->alive); try 17 #define CATCH() catch(std::exception& e) { \ 18 errlogPrintf("pvaLink %s fails %s: %s\n", CURRENT_FUNCTION, plink->precord->name, e.what()); \ 21 #define CHECK_VALID() if(!self->valid()) { DEBUG(self, <<CURRENT_FUNCTION<<" "<<self->channelName<<" !valid"); return -1;} 23 void pvaOpenLink(
DBLINK *plink)
37 DEBUG(
self, <<plink->
precord->name<<
" OPEN "<<self->channelName);
44 if(self->channelName.empty())
47 pvd::PVStructure::const_shared_pointer pvRequest(self->makeRequest());
51 std::ostringstream strm;
54 key = std::make_pair(self->channelName, strm.str());
57 std::tr1::shared_ptr<pvaLinkChannel> chan;
66 chan = it->second.lock();
84 if(!self->local || chan->providerName==
"QSRV"){
87 chan->links.insert(
self);
88 chan->links_changed =
true;
90 self->lchan.swap(chan);
92 self->lchan->debug |= !!
self->debug;
95 fprintf(
stderr,
"%s Error: local:true link to '%s' can't be fulfilled\n",
96 plink->
precord->name, self->channelName.c_str());
106 void pvaRemoveLink(
struct dbLocker *locker,
DBLINK *plink)
116 int pvaIsConnected(
const DBLINK *plink)
119 Guard G(self->lchan->lock);
121 bool ret =
self->valid();
129 int pvaGetDBFtype(
const DBLINK *plink)
132 Guard G(self->lchan->lock);
140 pvd::PVField::const_shared_pointer
value(self->getSubField(
"value"));
148 ftype = static_cast<const pvd::ScalarArray*>(
value->getField().get())->getElementType();
152 #define CASE(BASETYPE, PVATYPE, DBFTYPE, PVACODE) case pvd::pv##PVACODE: ret = DBF_##DBFTYPE; 153 #define CASE_REAL_INT64 155 #undef CASE_REAL_INT64 167 long pvaGetElements(
const DBLINK *plink,
long *nelements)
170 Guard G(self->lchan->lock);
174 if(self->fld_value && self->fld_value->getField()->getType()==
pvd::scalarArray)
175 ret = static_cast<const pvd::PVScalarArray*>(self->fld_value.get())->getLength();
184 long pvaGetValue(
DBLINK *plink,
short dbrType,
void *
pbuffer,
188 Guard G(self->lchan->lock);
198 plink->
precord->time =
self->snap_time;
204 if(self->fld_value) {
212 if(self->fld_seconds) {
214 if(self->fld_nanoseconds) {
215 self->snap_time.nsec =
self->fld_nanoseconds->getAs<
pvd::uint32>();
217 self->snap_time.nsec = 0u;
220 self->snap_time.secPastEpoch = 0u;
221 self->snap_time.nsec = 0u;
224 if(self->fld_severity) {
225 self->snap_severity =
self->fld_severity->getAs<
pvd::uint16>();
237 plink->
precord->time =
self->snap_time;
246 long pvaGetControlLimits(
const DBLINK *plink,
double *lo,
double *hi)
249 Guard G(self->lchan->lock);
252 if(self->fld_control) {
253 pvd::PVScalar::const_shared_pointer
value;
256 *lo = value ? value->
getAs<
double>() : 0.0;
260 *hi = value ? value->
getAs<
double>() : 0.0;
271 long pvaGetGraphicLimits(
const DBLINK *plink,
double *lo,
double *hi)
274 Guard G(self->lchan->lock);
277 if(self->fld_display) {
278 pvd::PVScalar::const_shared_pointer
value;
281 *lo = value ? value->
getAs<
double>() : 0.0;
285 *hi = value ? value->
getAs<
double>() : 0.0;
296 long pvaGetAlarmLimits(
const DBLINK *plink,
double *lolo,
double *lo,
297 double *hi,
double *hihi)
302 *lolo = *lo = *hi = *hihi = 0.0;
303 DEBUG(
self, <<plink->
precord->name<<
" "<<
CURRENT_FUNCTION<<
" "<<self->channelName<<
" "<<(lolo ? *lolo : 0)<<
" "<<(lo ? *lo : 0)<<
" "<<(hi ? *hi : 0)<<
" "<<(hihi ? *hihi : 0));
309 long pvaGetPrecision(
const DBLINK *plink,
short *precision)
323 long pvaGetUnits(
const DBLINK *plink,
char *units,
int unitsSize)
326 Guard G(self->lchan->lock);
329 if(unitsSize==0)
return 0;
331 if(units && self->fld_display) {
332 pvd::PVString::const_shared_pointer
value(std::tr1::static_pointer_cast<const pvd::PVString>(self->fld_display->getSubField(
"units")));
334 const std::string& egu = value->get();
335 strncpy(units, egu.c_str(), unitsSize);
340 units[unitsSize-1] =
'\0';
351 Guard G(self->lchan->lock);
355 *severity =
self->snap_severity;
361 DEBUG(
self, <<plink->
precord->name<<
" "<<
CURRENT_FUNCTION<<
" "<<self->channelName<<
" "<<(severity ? *severity : 0)<<
" "<<(status ? *status : 0));
370 Guard G(self->lchan->lock);
374 *pstamp =
self->snap_time;
387 #define CASE(BASETYPE, PVATYPE, DBFTYPE, PVACODE) case DBR_##DBFTYPE: return pvd::pv##PVACODE; 388 #define CASE_SKIP_BOOL 389 #define CASE_REAL_INT64 391 #undef CASE_SKIP_BOOL 392 #undef CASE_REAL_INT64 397 throw std::invalid_argument(
"Unsupported DBR code");
400 long pvaPutValue(
DBLINK *plink,
short dbrType,
401 const void *pbuffer,
long nRequest)
405 Guard G(self->lchan->lock);
407 if(nRequest < 0)
return -1;
409 if(!self->retry && !self->valid()) {
419 const char *sbuffer = (
const char*)pbuffer;
426 self->put_scratch = pvd::static_shared_vector_cast<
const void>(pvd::freeze(sval));
431 assert(
size_t(dbValueSize(dbrType)*nRequest) == val.
size());
435 self->put_scratch = pvd::freeze(val);
438 self->used_scratch =
true;
440 if(!self->defer)
self->lchan->put();
448 void pvaScanForward(
DBLINK *plink)
451 Guard G(self->lchan->lock);
453 if(!self->retry && !self->valid()) {
458 self->lchan->put(
true);
480 &pvaGetControlLimits,
481 &pvaGetGraphicLimits,
PVScalar is the base class for each scalar field.
#define assert(exp)
Declare that a condition should be true.
pointer data() const
Return Base pointer.
struct dbCommon * precord
ScalarType getScalarType(const string &pvalue)
const char * info(const char *key, const char *def=0)
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
long copyPVD2DBF(const pvd::PVField::const_shared_pointer &inraw, void *outbuf, short outdbf, long *outnReq)
std::pair< std::string, std::string > channels_key_t
shared_vector< void > allocArray(ScalarType id, size_t len)
Allocate an untyped array based on ScalarType.
int epicsStrCaseCmp(const char *s1, const char *s2)
epicsUInt32 secPastEpoch
seconds since 0000 Jan 1, 1990
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
#define NO_ALARM
The NO_ALARM value can be used as both a severity and a status.
#define POSIX_TIME_AT_EPICS_EPOCH
The EPICS Epoch is 00:00:00 Jan 1, 1990 UTC.
size_t size() const
Number of elements visible through this vector.
size_t epicsStrnLen(const char *s, size_t maxlen)
EPICS time stamp, for use from C code.
const char * dbGetFieldTypeString(int dbfType)
epicsUInt32 nsec
nanoseconds within second