diff --git a/src/ca/caChannel.cpp b/src/ca/caChannel.cpp index 21ed1e8..6d7d187 100644 --- a/src/ca/caChannel.cpp +++ b/src/ca/caChannel.cpp @@ -38,10 +38,10 @@ CAChannel::shared_pointer CAChannel::create(CAChannelProvider::shared_pointer co if(DEBUG_LEVEL>0) { cout<< "CAChannel::create " << channelName << endl; } - CAChannelPtr thisPtr( + CAChannelPtr caChannel( new CAChannel(channelName, channelProvider, channelRequester)); - thisPtr->activate(priority); - return thisPtr; + caChannel->activate(priority); + return caChannel; } static void ca_connection_handler(struct connection_handler_args args) @@ -487,6 +487,8 @@ void CAChannelGet::channelStateChange( throw std::runtime_error(mess); } +std::string CAChannelGet::getRequesterName() { return "CAChannelGet";} + void CAChannelGet::channelDisconnect(bool destroy) { if(DEBUG_LEVEL>0) { @@ -498,8 +500,6 @@ void CAChannelGet::channelDisconnect(bool destroy) if(!destroy) channel->addChannelGet(shared_from_this()); } -/* --------------- epics::pvAccess::ChannelGet --------------- */ - namespace { static void ca_get_handler(struct event_handler_args args) @@ -622,6 +622,8 @@ void CAChannelPut::channelStateChange( throw std::runtime_error(mess); } +std::string CAChannelPut::getRequesterName() { return "CAChannelPut";} + void CAChannelPut::channelDisconnect(bool destroy) { if(DEBUG_LEVEL>0) { @@ -866,6 +868,7 @@ void CAChannelMonitor::channelStateChange( throw std::runtime_error(mess); } +std::string CAChannelMonitor::getRequesterName() { return "CAChannelMonitor";} void CAChannelMonitor::channelDisconnect(bool destroy) { diff --git a/src/ca/caChannel.h b/src/ca/caChannel.h index 6d49186..a79b65b 100644 --- a/src/ca/caChannel.h +++ b/src/ca/caChannel.h @@ -22,7 +22,6 @@ namespace epics { namespace pvAccess { namespace ca { - class CAChannelGetField; typedef std::tr1::shared_ptr CAChannelGetFieldPtr; typedef std::tr1::weak_ptr CAChannelGetFieldWPtr; @@ -53,22 +52,18 @@ class CAChannel : public Channel, public std::tr1::enable_shared_from_this { - public: POINTER_DEFINITIONS(CAChannel); - static size_t num_instances; - - static CAChannelPtr create(CAChannelProvider::shared_pointer const & channelProvider, - std::string const & channelName, - short priority, - ChannelRequester::shared_pointer const & channelRequester); - + static CAChannelPtr create( + CAChannelProvider::shared_pointer const & channelProvider, + std::string const & channelName, + short priority, + ChannelRequester::shared_pointer const & channelRequester); virtual ~CAChannel(); void connected(); void disconnected(); - chid getChannelID(); virtual std::tr1::shared_ptr getProvider(); @@ -76,54 +71,36 @@ public: virtual ConnectionState getConnectionState(); virtual std::string getChannelName(); virtual std::tr1::shared_ptr getChannelRequester(); - virtual void getField(GetFieldRequester::shared_pointer const & requester,std::string const & subField); - virtual AccessRights getAccessRights(epics::pvData::PVField::shared_pointer const & pvField); - virtual ChannelGet::shared_pointer createChannelGet( ChannelGetRequester::shared_pointer const & channelGetRequester, epics::pvData::PVStructurePtr const & pvRequest); - virtual ChannelPut::shared_pointer createChannelPut( ChannelPutRequester::shared_pointer const & channelPutRequester, epics::pvData::PVStructurePtr const & pvRequest); - virtual Monitor::shared_pointer createMonitor( MonitorRequester::shared_pointer const & monitorRequester, epics::pvData::PVStructurePtr const & pvRequest); - virtual void printInfo(std::ostream& out); - /* ---------------------------------------------------------------- */ - void attachContext(); - void addChannelGet(const CAChannelGetPtr & get); void addChannelPut(const CAChannelPutPtr & get); void addChannelMonitor(const CAChannelMonitorPtr & get); void disconnectChannel(); - - private: - - /* --------------- Destroyable --------------- */ - virtual void destroy() {} - CAChannel(std::string const & channelName, CAChannelProvider::shared_pointer const & channelProvider, ChannelRequester::shared_pointer const & channelRequester); void activate(short priority); std::string channelName; - CAChannelProviderWPtr channelProvider; ChannelRequester::weak_pointer channelRequester; - chid channelID; bool channelCreated; - epics::pvData::Mutex requestsMutex; std::queue getFieldQueue; @@ -142,45 +119,32 @@ class CAChannelGet : public ChannelBaseRequester, public std::tr1::enable_shared_from_this { - public: POINTER_DEFINITIONS(CAChannelGet); - static size_t num_instances; - static CAChannelGet::shared_pointer create(CAChannel::shared_pointer const & channel, ChannelGetRequester::shared_pointer const & channelGetRequester, epics::pvData::PVStructurePtr const & pvRequest); - virtual ~CAChannelGet(); - void getDone(struct event_handler_args &args); - - /* --------------- epics::pvAccess::ChannelGet --------------- */ virtual void get(); - - /* --------------- epics::pvData::ChannelRequest --------------- */ virtual Channel::shared_pointer getChannel(); virtual void cancel(); virtual void lastRequest(); - /* --------------- ChannelRequester --------------- */ virtual void channelCreated( const epics::pvData::Status& status, Channel::shared_pointer const & channel); virtual void channelStateChange( Channel::shared_pointer const & channel, Channel::ConnectionState cosnectionState); - virtual std::string getRequesterName() { return "CAChannelGet";} - /* --------------- ChannelBaseRequester --------------- */ + virtual std::string getRequesterName(); virtual void channelDisconnect(bool destroy); void activate(); private: - /* --------------- Destroyable --------------- */ - virtual void destroy() {} - + virtual void destroy() {} CAChannelGet(CAChannel::shared_pointer const & _channel, ChannelGetRequester::shared_pointer const & _channelGetRequester, epics::pvData::PVStructurePtr const & pvRequest); @@ -188,14 +152,11 @@ private: CAChannelPtr channel; ChannelGetRequester::weak_pointer channelGetRequester; epics::pvData::PVStructurePtr const & pvRequest; - DbdToPvPtr dbdToPv; epics::pvData::PVStructure::shared_pointer pvStructure; epics::pvData::BitSet::shared_pointer bitSet; }; - - class CAChannelPut : public ChannelPut, public ChannelRequester, @@ -205,58 +166,40 @@ class CAChannelPut : public: POINTER_DEFINITIONS(CAChannelPut); - static size_t num_instances; - static CAChannelPut::shared_pointer create(CAChannel::shared_pointer const & channel, ChannelPutRequester::shared_pointer const & channelPutRequester, epics::pvData::PVStructurePtr const & pvRequest); - virtual ~CAChannelPut(); - void getDone(struct event_handler_args &args); - - /* --------------- epics::pvAccess::ChannelPut --------------- */ - virtual void put( epics::pvData::PVStructure::shared_pointer const & pvPutStructure, epics::pvData::BitSet::shared_pointer const & putBitSet ); virtual void get(); - - /* --------------- epics::pvData::ChannelRequest --------------- */ - virtual Channel::shared_pointer getChannel(); virtual void cancel(); virtual void lastRequest(); - /* --------------- ChannelRequester --------------- */ virtual void channelCreated( const epics::pvData::Status& status, Channel::shared_pointer const & channel); virtual void channelStateChange( Channel::shared_pointer const & channel, Channel::ConnectionState connectionState); - virtual std::string getRequesterName() { return "CAChannelPut";} - /* --------------- ChannelBaseRequester --------------- */ + virtual std::string getRequesterName(); virtual void channelDisconnect(bool destroy); void activate(); - private: - /* --------------- Destroyable --------------- */ - - virtual void destroy() {} - + virtual void destroy() {} CAChannelPut(CAChannel::shared_pointer const & _channel, ChannelPutRequester::shared_pointer const & _channelPutRequester, epics::pvData::PVStructurePtr const & pvRequest); - CAChannelPtr channel; ChannelPutRequester::weak_pointer channelPutRequester; const epics::pvData::PVStructure::shared_pointer pvRequest; bool block; - DbdToPvPtr dbdToPv; epics::pvData::PVStructure::shared_pointer pvStructure; epics::pvData::BitSet::shared_pointer bitSet; @@ -274,46 +217,34 @@ class CAChannelMonitor : public: POINTER_DEFINITIONS(CAChannelMonitor); - static size_t num_instances; - static CAChannelMonitor::shared_pointer create(CAChannel::shared_pointer const & channel, MonitorRequester::shared_pointer const & monitorRequester, epics::pvData::PVStructurePtr const & pvRequest); - virtual ~CAChannelMonitor(); - void subscriptionEvent(struct event_handler_args &args); - /* --------------- Monitor --------------- */ - virtual epics::pvData::Status start(); virtual epics::pvData::Status stop(); virtual MonitorElementPtr poll(); virtual void release(MonitorElementPtr const & monitorElement); - - /* --------------- epics::pvData::ChannelRequest --------------- */ virtual void cancel(); - /* --------------- ChannelRequester --------------- */ + virtual void channelCreated( const epics::pvData::Status& status, Channel::shared_pointer const & channel); virtual void channelStateChange( Channel::shared_pointer const & channel, Channel::ConnectionState connectionState); - virtual std::string getRequesterName() { return "CAChannelMonitor";} - /* --------------- ChannelBaseRequester --------------- */ + virtual std::string getRequesterName(); + virtual void channelDisconnect(bool destroy); void activate(); private: - /* --------------- Destroyable --------------- */ virtual void destroy() {} - CAChannelMonitor(CAChannel::shared_pointer const & _channel, MonitorRequester::shared_pointer const & _monitorRequester, epics::pvData::PVStructurePtr const & pvRequest); - - CAChannelPtr channel; MonitorRequester::weak_pointer monitorRequester; const epics::pvData::PVStructure::shared_pointer pvRequest; diff --git a/src/ca/dbdToPv.cpp b/src/ca/dbdToPv.cpp index dc05ef8..fd9c361 100644 --- a/src/ca/dbdToPv.cpp +++ b/src/ca/dbdToPv.cpp @@ -28,7 +28,6 @@ namespace epics { namespace pvAccess { namespace ca { -#define CA_TIMEOUT 2.0 #define CA_PRIORITY 50 static void enumChoicesHandler(struct event_handler_args args) @@ -58,8 +57,7 @@ static void putHandler(struct event_handler_args args) DbdToPvPtr DbdToPv::create( CAChannelPtr const & caChannel, PVStructurePtr const & pvRequest, - IOType ioType - ) + IOType ioType) { DbdToPvPtr dbdToPv(new DbdToPv(ioType)); dbdToPv->activate(caChannel,pvRequest); @@ -77,9 +75,9 @@ DbdToPv::DbdToPv(IOType ioType) isArray(false), firstTime(true), caValueType(-1), - caRequestType(-1) -{ -} + caRequestType(-1), + maxElements(0) +{} static ScalarType dbr2ST[] = { @@ -153,11 +151,12 @@ void DbdToPv::activate( case getIO : break; case putIO: alarmRequested = false; - timeStampRequested = false; // no break - case monitorIO: + timeStampRequested = false; displayRequested = false; controlRequested = false; valueAlarmRequested = false; + break; + case monitorIO: break; } StandardFieldPtr standardField = getStandardField(); if(channelType==DBR_ENUM) @@ -165,18 +164,15 @@ void DbdToPv::activate( displayRequested = false; controlRequested = false; valueAlarmRequested = false; - caRequestType = DBR_ENUM; string properties; if(alarmRequested && timeStampRequested) { properties += "alarm,timeStamp"; - caRequestType += DBR_TIME_STRING + caValueType; } else if(timeStampRequested) { properties += "timeStamp"; - caRequestType += DBR_TIME_STRING + caValueType; } else if(alarmRequested) { properties += "alarm"; - caRequestType += DBR_STS_STRING + caValueType; } + caRequestType = (properties.size()==0 ? DBR_ENUM : DBR_TIME_ENUM); structure = standardField->enumerated(properties); int result = ca_array_get_callback(DBR_GR_ENUM, 1, @@ -192,7 +188,8 @@ void DbdToPv::activate( // and will guarantee that enumChoicesHandler is called first return; } - if(ca_element_count(channelID)!=1) isArray = true; + maxElements = ca_element_count(channelID); + if(maxElements!=1) isArray = true; if(isArray) { controlRequested = false; @@ -205,7 +202,6 @@ void DbdToPv::activate( valueAlarmRequested = false; } if(controlRequested || displayRequested || valueAlarmRequested) timeStampRequested = false; - FieldCreatePtr fieldCreate(FieldCreate::getFieldCreate()); PVDataCreatePtr pvDataCreate(PVDataCreate::getPVDataCreate()); FieldBuilderPtr fieldBuilder(fieldCreate->createFieldBuilder()); @@ -241,11 +237,11 @@ void DbdToPv::activate( caRequestType = caValueType; if(displayRequested || controlRequested || valueAlarmRequested) { - caRequestType = DBR_CTRL_STRING + caValueType; - } else if(timeStampRequested) { - caRequestType = DBR_TIME_STRING + caValueType; - } else if(alarmRequested) { - caRequestType = DBR_STS_STRING + caValueType; + caRequestType = dbf_type_to_DBR_CTRL(caValueType); + } else if(timeStampRequested || alarmRequested) { + caRequestType = dbf_type_to_DBR_TIME(caValueType); + } else { + caRequestType = dbf_type_to_DBR(caValueType); } if(displayRequested) { chid channelID; @@ -308,6 +304,54 @@ PVStructurePtr DbdToPv::createPVStructure() return getPVDataCreate()->createPVStructure(structure); } +template +void copy_DBRScalar(const void * dbr, PVScalar::shared_pointer const & pvScalar) +{ + std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvScalar); + value->put(static_cast(dbr)[0]); +} + +template +void copy_DBRScalarArray(const void * dbr, unsigned count, PVScalarArray::shared_pointer const & pvArray) +{ + std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvArray); + typename pvT::svector temp(value->reuse()); + temp.resize(count); + std::copy( + static_cast(dbr), + static_cast(dbr) + count, + temp.begin()); + value->replace(freeze(temp)); +} + +template +void get_DBRControl(const void * dbr, double *upper_ctrl_limit,double *lower_ctrl_limit) +{ + *upper_ctrl_limit = static_cast(dbr)->upper_ctrl_limit; + *lower_ctrl_limit = static_cast(dbr)->lower_ctrl_limit; +} + +template +void get_DBRDisplay( + const void * dbr, double *upper_disp_limit,double *lower_disp_limit,string *units) +{ + *upper_disp_limit = static_cast(dbr)->upper_disp_limit; + *lower_disp_limit = static_cast(dbr)->lower_disp_limit; + *units = static_cast(dbr)->units; +} + +template +void get_DBRValueAlarm( + const void * dbr, + double *upper_alarm_limit,double *upper_warning_limit, + double *lower_warning_limit,double *lower_alarm_limit) +{ + *upper_alarm_limit = static_cast(dbr)->upper_alarm_limit; + *upper_warning_limit = static_cast(dbr)->upper_warning_limit; + *lower_warning_limit = static_cast(dbr)->lower_warning_limit; + *lower_alarm_limit = static_cast(dbr)->lower_alarm_limit; +} + Status DbdToPv::getFromDBD( PVStructurePtr const & pvStructure, BitSet::shared_pointer const & bitSet, @@ -321,8 +365,43 @@ Status DbdToPv::getFromDBD( if(fieldRequested) { void * value = dbr_value_ptr(args.dbr,caRequestType); - long count = args.count; - switch(caValueType) { + if(isArray) { + long count = args.count; + PVScalarArrayPtr pvValue = pvStructure->getSubField("value"); + switch(caValueType) { + case DBR_STRING: + { + const dbr_string_t *dbrval = static_cast(value); + PVStringArrayPtr pvValue = pvStructure->getSubField("value"); + PVStringArray::svector arr(pvValue->reuse()); + arr.resize(count); + std::copy(dbrval, dbrval + count, arr.begin()); + pvValue->replace(freeze(arr)); + break; + } + case DBR_CHAR: + copy_DBRScalarArray(value,count,pvValue); + break; + case DBR_SHORT: + copy_DBRScalarArray(value,count,pvValue); + break; + case DBR_LONG: + copy_DBRScalarArray(value,count,pvValue); + break; + case DBR_FLOAT: + copy_DBRScalarArray(value,count,pvValue); + break; + case DBR_DOUBLE: + copy_DBRScalarArray(value,count,pvValue); + break; + default: + Status errorStatus( + Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD logic error")); + return errorStatus; + } + } else { + PVScalarPtr pvValue = pvStructure->getSubField("value"); + switch(caValueType) { case DBR_ENUM: { const dbr_enum_t *dbrval = static_cast(value); @@ -342,427 +421,59 @@ Status DbdToPv::getFromDBD( } break; } - case DBR_STRING: - { - const dbr_string_t *dbrval = static_cast(value); - if(isArray) { - PVStringArrayPtr pvValue = pvStructure->getSubField("value"); - PVStringArray::svector arr(pvValue->reuse()); - arr.resize(count); - std::copy(dbrval, dbrval + count, arr.begin()); - pvValue->replace(freeze(arr)); - } else { - PVStringPtr pvValue = pvStructure->getSubField("value"); - pvValue->put(*dbrval); - } - break; - } - case DBR_CHAR: - { - const dbr_char_t *dbrval = static_cast(value); - if(isArray) { - PVByteArrayPtr pvValue = pvStructure->getSubField("value"); - PVByteArray::svector arr(pvValue->reuse()); - arr.resize(count); - for(long i=0; ireplace(freeze(arr)); - } else { - PVBytePtr pvValue = pvStructure->getSubField("value"); - pvValue->put(*dbrval); - } - break; - } - case DBR_SHORT: - { - const dbr_short_t *dbrval = static_cast(value); - if(isArray) { - PVShortArrayPtr pvValue = pvStructure->getSubField("value"); - PVShortArray::svector arr(pvValue->reuse()); - arr.resize(count); - for(long i=0; ireplace(freeze(arr)); - } else { - PVShortPtr pvValue = pvStructure->getSubField("value"); - pvValue->put(*dbrval); - } - break; - } - case DBR_LONG: - { - const dbr_int_t *dbrval = static_cast(value); - if(isArray) { - PVIntArrayPtr pvValue = pvStructure->getSubField("value"); - PVIntArray::svector arr(pvValue->reuse()); - arr.resize(count); - for(long i=0; ireplace(freeze(arr)); - } else { - PVIntPtr pvValue = pvStructure->getSubField("value"); - pvValue->put(*dbrval); - } - break; - } - case DBR_FLOAT: - { - const dbr_float_t *dbrval = static_cast(value); - if(isArray) { - PVFloatArrayPtr pvValue = pvStructure->getSubField("value"); - PVFloatArray::svector arr(pvValue->reuse()); - arr.resize(count); - for(long i=0; ireplace(freeze(arr)); - } else { - PVFloatPtr pvValue = pvStructure->getSubField("value"); - pvValue->put(*dbrval); - } - break; - } - case DBR_DOUBLE: - { - const dbr_double_t *dbrval = static_cast(value); - if(isArray) { - PVDoubleArrayPtr pvValue - = pvStructure->getSubField("value"); - PVDoubleArray::svector arr(pvValue->reuse()); - arr.resize(count); - for(long i=0; ireplace(freeze(arr)); - } else { - PVDoublePtr pvValue = pvStructure->getSubField("value"); - pvValue->put(*dbrval); - } - break; - } + case DBR_STRING: copy_DBRScalar(value,pvValue); break; + case DBR_CHAR: copy_DBRScalar(value,pvValue); break; + case DBR_SHORT: copy_DBRScalar(value,pvValue); break; + case DBR_LONG: copy_DBRScalar(value,pvValue); break; + case DBR_FLOAT: copy_DBRScalar(value,pvValue); break; + case DBR_DOUBLE: copy_DBRScalar(value,pvValue); break; default: Status errorStatus( - Status::STATUSTYPE_ERROR, string("DbdToPv::FromDBD logic error")); + Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD logic error")); return errorStatus; + } } if(caValueType!=DBR_ENUM) { bitSet->set(pvStructure->getSubField("value")->getFieldOffset()); } } - chtype type = args.type; - dbr_short_t status = 0; - dbr_short_t severity = 0; - epicsTimeStamp stamp = {0,0}; - if(caRequestType>=DBR_CTRL_STRING) { - string units; - string format; - double upper_disp_limit = 0.0; - double lower_disp_limit = 0.0; - double upper_alarm_limit = 0.0; - double upper_warning_limit = 0.0; - double lower_warning_limit = 0.0; - double lower_alarm_limit = 0.0; - double upper_ctrl_limit = 0.0; - double lower_ctrl_limit = 0.0; - switch(type) { - case DBR_CTRL_CHAR: - { - const dbr_ctrl_char *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - units = data->units; - upper_disp_limit = data->upper_disp_limit; - lower_disp_limit = data->lower_disp_limit; - upper_alarm_limit = data->upper_alarm_limit; - upper_warning_limit = data->upper_warning_limit; - lower_warning_limit = data->lower_warning_limit; - lower_alarm_limit = data->lower_alarm_limit; - upper_ctrl_limit = data->upper_ctrl_limit; - lower_ctrl_limit = data->lower_ctrl_limit; - format = "I4"; - break; - } - case DBR_CTRL_SHORT: - { - const dbr_ctrl_short *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - units = data->units; - upper_disp_limit = data->upper_disp_limit; - lower_disp_limit = data->lower_disp_limit; - upper_alarm_limit = data->upper_alarm_limit; - upper_warning_limit = data->upper_warning_limit; - lower_warning_limit = data->lower_warning_limit; - lower_alarm_limit = data->lower_alarm_limit; - upper_ctrl_limit = data->upper_ctrl_limit; - lower_ctrl_limit = data->lower_ctrl_limit; - format = "I6"; - break; - } - case DBR_CTRL_LONG: - { - const dbr_ctrl_long *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - units = data->units; - upper_disp_limit = data->upper_disp_limit; - lower_disp_limit = data->lower_disp_limit; - upper_alarm_limit = data->upper_alarm_limit; - upper_warning_limit = data->upper_warning_limit; - lower_warning_limit = data->lower_warning_limit; - lower_alarm_limit = data->lower_alarm_limit; - upper_ctrl_limit = data->upper_ctrl_limit; - lower_ctrl_limit = data->lower_ctrl_limit; - format = "I12"; - break; - } - case DBR_CTRL_FLOAT: - { - const dbr_ctrl_float *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - units = data->units; - upper_disp_limit = data->upper_disp_limit; - lower_disp_limit = data->lower_disp_limit; - upper_alarm_limit = data->upper_alarm_limit; - upper_warning_limit = data->upper_warning_limit; - lower_warning_limit = data->lower_warning_limit; - lower_alarm_limit = data->lower_alarm_limit; - upper_ctrl_limit = data->upper_ctrl_limit; - lower_ctrl_limit = data->lower_ctrl_limit; - int prec = data->precision; - ostringstream s; - s << "F" << prec + 6 << "." << prec; - format = s.str(); - break; - } - case DBR_CTRL_DOUBLE: - { - const dbr_ctrl_double *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - units = data->units; - upper_disp_limit = data->upper_disp_limit; - lower_disp_limit = data->lower_disp_limit; - upper_alarm_limit = data->upper_alarm_limit; - upper_warning_limit = data->upper_warning_limit; - lower_warning_limit = data->lower_warning_limit; - lower_alarm_limit = data->lower_alarm_limit; - upper_ctrl_limit = data->upper_ctrl_limit; - lower_ctrl_limit = data->lower_ctrl_limit; - int prec = data->precision; - ostringstream s; - s << "F" << prec + 6 << "." << prec; - format = s.str(); - break; - } - default : - throw std::runtime_error("DbdToPv::getDone logic error"); - } - if(displayRequested) - { - PVStructurePtr pvDisplay(pvStructure->getSubField("display")); - if(caDisplay.lower_disp_limit!=lower_disp_limit) { - caDisplay.lower_disp_limit = lower_disp_limit; - PVDoublePtr pvDouble = pvDisplay->getSubField("limitLow"); - pvDouble->put(lower_disp_limit); - bitSet->set(pvDouble->getFieldOffset()); - } - if(caDisplay.upper_disp_limit!=upper_disp_limit) { - caDisplay.upper_disp_limit = upper_disp_limit; - PVDoublePtr pvDouble = pvDisplay->getSubField("limitHigh"); - pvDouble->put(upper_disp_limit); - bitSet->set(pvDouble->getFieldOffset()); - } - if(caDisplay.units!=units) { - caDisplay.units = units; - PVStringPtr pvString = pvDisplay->getSubField("units"); - pvString->put(units); - bitSet->set(pvString->getFieldOffset()); - } - if(caDisplay.format!=format) { - caDisplay.format = format; - PVStringPtr pvString = pvDisplay->getSubField("format"); - pvString->put(format); - bitSet->set(pvString->getFieldOffset()); - } - if(!description.empty()) - { - PVStringPtr pvString = pvDisplay->getSubField("description"); - if(description.compare(pvString->get()) !=0) { - pvString->put(description); - bitSet->set(pvString->getFieldOffset()); - } - } - } - if(controlRequested) - { - PVStructurePtr pvControl(pvStructure->getSubField("control")); - if(caControl.upper_ctrl_limit!=upper_ctrl_limit) { - caControl.upper_ctrl_limit = upper_ctrl_limit; - PVDoublePtr pv = pvControl->getSubField("limitHigh"); - pv->put(upper_ctrl_limit); - bitSet->set(pv->getFieldOffset()); - } - if(caControl.lower_ctrl_limit!=lower_ctrl_limit) { - caControl.lower_ctrl_limit = lower_ctrl_limit; - PVDoublePtr pv = pvControl->getSubField("limitLow"); - pv->put(lower_ctrl_limit); - bitSet->set(pv->getFieldOffset()); - } - } - if(valueAlarmRequested) { - ConvertPtr convert(getConvert()); - PVStructurePtr pvValueAlarm(pvStructure->getSubField("valueAlarm")); - if(caValueAlarm.upper_alarm_limit!=upper_alarm_limit) { - caValueAlarm.upper_alarm_limit = upper_alarm_limit; - PVScalarPtr pv = pvValueAlarm->getSubField("highAlarmLimit"); - convert->fromDouble(pv,upper_alarm_limit); - bitSet->set(pv->getFieldOffset()); - } - if(caValueAlarm.upper_warning_limit!=upper_warning_limit) { - caValueAlarm.upper_warning_limit = upper_warning_limit; - PVScalarPtr pv = pvValueAlarm->getSubField("highWarningLimit"); - convert->fromDouble(pv,upper_warning_limit); - bitSet->set(pv->getFieldOffset()); - } - if(caValueAlarm.lower_warning_limit!=lower_warning_limit) { - caValueAlarm.lower_warning_limit = lower_warning_limit; - PVScalarPtr pv = pvValueAlarm->getSubField("lowWarningLimit"); - convert->fromDouble(pv,lower_warning_limit); - bitSet->set(pv->getFieldOffset()); - } - if(caValueAlarm.lower_alarm_limit!=lower_alarm_limit) { - caValueAlarm.lower_alarm_limit = lower_alarm_limit; - PVScalarPtr pv = pvValueAlarm->getSubField("lowAlarmLimit"); - convert->fromDouble(pv,lower_alarm_limit); - bitSet->set(pv->getFieldOffset()); - } - } - } else if(caRequestType>=DBR_TIME_STRING) { - switch(type) { - case DBR_TIME_STRING: - { - const dbr_time_string *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - stamp = data->stamp; - break; - } - case DBR_TIME_CHAR: - { - const dbr_time_char *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - stamp = data->stamp; - break; - } - case DBR_TIME_SHORT: - { - const dbr_time_short *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - stamp = data->stamp; - break; - } - case DBR_TIME_LONG: - { - const dbr_time_long *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - stamp = data->stamp; - break; - } - case DBR_TIME_FLOAT: - { - const dbr_time_float *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - stamp = data->stamp; - break; - } - case DBR_TIME_DOUBLE: - { - const dbr_time_double *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - stamp = data->stamp; - break; - } - default: - throw std::runtime_error("DbdToPv::getDone logic error"); - } - } else if(caRequestType>=DBR_STS_STRING) { - switch(type) { - case DBR_STS_STRING: - { - const dbr_sts_string *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - break; - } - case DBR_STS_CHAR: - { - const dbr_sts_char *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - break; - } - case DBR_STS_SHORT: - { - const dbr_sts_short *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - break; - } - case DBR_STS_LONG: - { - const dbr_sts_long *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - break; - } - case DBR_STS_FLOAT: - { - const dbr_sts_float *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - break; - } - case DBR_STS_DOUBLE: - { - const dbr_sts_double *data = static_cast(args.dbr); - status = data->status; - severity = data->severity; - break; - } - default: - throw std::runtime_error("DbdToPv::getDone logic error"); - } - } if(alarmRequested) { - bool statusChanged = false; - bool severityChanged = false; - PVStructurePtr pvAlarm(pvStructure->getSubField("alarm")); - PVIntPtr pvSeverity(pvAlarm->getSubField("severity")); - if(caAlarm.severity!=severity) { - caAlarm.severity = severity; - pvSeverity->put(severity); - severityChanged = true; - } - PVStringPtr pvMessage(pvAlarm->getSubField("message")); - PVIntPtr pvStatus(pvAlarm->getSubField("status")); - if(caAlarm.status!=status) { - caAlarm.status = status; - pvStatus->put(status); - string message("UNKNOWN STATUS"); - if(status<=ALARM_NSTATUS) message = string(epicsAlarmConditionStrings[status]); - pvMessage->put(message); - statusChanged = true; - } - if(statusChanged&&severityChanged) { - bitSet->set(pvAlarm->getFieldOffset()); - } else if(severityChanged) { - bitSet->set(pvSeverity->getFieldOffset()); - } else if(statusChanged) { - bitSet->set(pvStatus->getFieldOffset()); - bitSet->set(pvMessage->getFieldOffset()); - } + // Note that status and severity are aways the first two members of DBR_ + const dbr_sts_string *data = static_cast(args.dbr); + dbr_short_t status = data->status; + dbr_short_t severity = data->severity; + bool statusChanged = false; + bool severityChanged = false; + PVStructurePtr pvAlarm(pvStructure->getSubField("alarm")); + PVIntPtr pvSeverity(pvAlarm->getSubField("severity")); + if(caAlarm.severity!=severity) { + caAlarm.severity = severity; + pvSeverity->put(severity); + severityChanged = true; + } + PVStringPtr pvMessage(pvAlarm->getSubField("message")); + PVIntPtr pvStatus(pvAlarm->getSubField("status")); + if(caAlarm.status!=status) { + caAlarm.status = status; + pvStatus->put(status); + string message("UNKNOWN STATUS"); + if(status<=ALARM_NSTATUS) message = string(epicsAlarmConditionStrings[status]); + pvMessage->put(message); + statusChanged = true; + } + if(statusChanged&&severityChanged) { + bitSet->set(pvAlarm->getFieldOffset()); + } else if(severityChanged) { + bitSet->set(pvSeverity->getFieldOffset()); + } else if(statusChanged) { + bitSet->set(pvStatus->getFieldOffset()); + bitSet->set(pvMessage->getFieldOffset()); + } } if(timeStampRequested) { + // Note that epicsTimeStamp always follows status and severity + const dbr_time_string *data = static_cast(args.dbr); + epicsTimeStamp stamp = data->stamp; PVStructurePtr pvTimeStamp(pvStructure->getSubField("timeStamp")); if(caTimeStamp.secPastEpoch!=stamp.secPastEpoch) { caTimeStamp.secPastEpoch = stamp.secPastEpoch; @@ -776,7 +487,172 @@ Status DbdToPv::getFromDBD( pvNano->put(stamp.nsec); bitSet->set(pvNano->getFieldOffset()); } - + } + if(controlRequested) + { + double upper_ctrl_limit = 0.0; + double lower_ctrl_limit = 0.0; + switch(caRequestType) { + case DBR_CTRL_CHAR: + get_DBRControl(args.dbr,&upper_ctrl_limit,&lower_ctrl_limit); break; + case DBR_CTRL_SHORT: + get_DBRControl(args.dbr,&upper_ctrl_limit,&lower_ctrl_limit); break; + case DBR_CTRL_LONG: + get_DBRControl(args.dbr,&upper_ctrl_limit,&lower_ctrl_limit); break; + case DBR_CTRL_FLOAT: + get_DBRControl(args.dbr,&upper_ctrl_limit,&lower_ctrl_limit); break; + case DBR_CTRL_DOUBLE: + get_DBRControl(args.dbr,&upper_ctrl_limit,&lower_ctrl_limit); break; + default : + throw std::runtime_error("DbdToPv::getFromDBD logic error"); + } + PVStructurePtr pvControl(pvStructure->getSubField("control")); + if(caControl.upper_ctrl_limit!=upper_ctrl_limit) { + caControl.upper_ctrl_limit = upper_ctrl_limit; + PVDoublePtr pv = pvControl->getSubField("limitHigh"); + pv->put(upper_ctrl_limit); + bitSet->set(pv->getFieldOffset()); + } + if(caControl.lower_ctrl_limit!=lower_ctrl_limit) { + caControl.lower_ctrl_limit = lower_ctrl_limit; + PVDoublePtr pv = pvControl->getSubField("limitLow"); + pv->put(lower_ctrl_limit); + bitSet->set(pv->getFieldOffset()); + } + } + if(displayRequested) + { + string units; + string format; + double upper_disp_limit = 0.0; + double lower_disp_limit = 0.0; + switch(caRequestType) { + case DBR_CTRL_CHAR: + get_DBRDisplay(args.dbr,&upper_disp_limit,&lower_disp_limit,&units); + format = "I4"; break; + case DBR_CTRL_SHORT: + get_DBRDisplay(args.dbr,&upper_disp_limit,&lower_disp_limit,&units); + format = "I6"; break; + case DBR_CTRL_LONG: + get_DBRDisplay(args.dbr,&upper_disp_limit,&lower_disp_limit,&units); + format = "I12"; break; + case DBR_CTRL_FLOAT: + get_DBRDisplay(args.dbr,&upper_disp_limit,&lower_disp_limit,&units); + { + const dbr_ctrl_float *data = static_cast(args.dbr); + int prec = data->precision; + ostringstream s; + s << "F" << prec + 6 << "." << prec; + format = s.str(); + } + break; + case DBR_CTRL_DOUBLE: + get_DBRDisplay(args.dbr,&upper_disp_limit,&lower_disp_limit,&units); + { + const dbr_ctrl_double *data = static_cast(args.dbr); + int prec = data->precision; + ostringstream s; + s << "F" << prec + 6 << "." << prec; + format = s.str(); + } + break; + default : + throw std::runtime_error("DbdToPv::getFromDBD logic error"); + } + PVStructurePtr pvDisplay(pvStructure->getSubField("display")); + if(caDisplay.lower_disp_limit!=lower_disp_limit) { + caDisplay.lower_disp_limit = lower_disp_limit; + PVDoublePtr pvDouble = pvDisplay->getSubField("limitLow"); + pvDouble->put(lower_disp_limit); + bitSet->set(pvDouble->getFieldOffset()); + } + if(caDisplay.upper_disp_limit!=upper_disp_limit) { + caDisplay.upper_disp_limit = upper_disp_limit; + PVDoublePtr pvDouble = pvDisplay->getSubField("limitHigh"); + pvDouble->put(upper_disp_limit); + bitSet->set(pvDouble->getFieldOffset()); + } + if(caDisplay.units!=units) { + caDisplay.units = units; + PVStringPtr pvString = pvDisplay->getSubField("units"); + pvString->put(units); + bitSet->set(pvString->getFieldOffset()); + } + if(caDisplay.format!=format) { + caDisplay.format = format; + PVStringPtr pvString = pvDisplay->getSubField("format"); + pvString->put(format); + bitSet->set(pvString->getFieldOffset()); + } + if(!description.empty()) + { + PVStringPtr pvString = pvDisplay->getSubField("description"); + if(description.compare(pvString->get()) !=0) { + pvString->put(description); + bitSet->set(pvString->getFieldOffset()); + } + } + } + if(valueAlarmRequested) { + double upper_alarm_limit = 0.0; + double upper_warning_limit = 0.0; + double lower_warning_limit = 0.0; + double lower_alarm_limit = 0.0; + switch(caRequestType) { + case DBR_CTRL_CHAR: + get_DBRValueAlarm(args.dbr, + &upper_alarm_limit,&upper_warning_limit, + &lower_warning_limit,&lower_alarm_limit); + break; + case DBR_CTRL_SHORT: + get_DBRValueAlarm(args.dbr, + &upper_alarm_limit,&upper_warning_limit, + &lower_warning_limit,&lower_alarm_limit); + break; + case DBR_CTRL_LONG: + get_DBRValueAlarm(args.dbr, + &upper_alarm_limit,&upper_warning_limit, + &lower_warning_limit,&lower_alarm_limit); + break; + case DBR_CTRL_FLOAT: + get_DBRValueAlarm(args.dbr, + &upper_alarm_limit,&upper_warning_limit, + &lower_warning_limit,&lower_alarm_limit); + break; + case DBR_CTRL_DOUBLE: + get_DBRValueAlarm(args.dbr, + &upper_alarm_limit,&upper_warning_limit, + &lower_warning_limit,&lower_alarm_limit); + break; + default : + throw std::runtime_error("DbdToPv::getFromDBD logic error"); + } + ConvertPtr convert(getConvert()); + PVStructurePtr pvValueAlarm(pvStructure->getSubField("valueAlarm")); + if(caValueAlarm.upper_alarm_limit!=upper_alarm_limit) { + caValueAlarm.upper_alarm_limit = upper_alarm_limit; + PVScalarPtr pv = pvValueAlarm->getSubField("highAlarmLimit"); + convert->fromDouble(pv,upper_alarm_limit); + bitSet->set(pv->getFieldOffset()); + } + if(caValueAlarm.upper_warning_limit!=upper_warning_limit) { + caValueAlarm.upper_warning_limit = upper_warning_limit; + PVScalarPtr pv = pvValueAlarm->getSubField("highWarningLimit"); + convert->fromDouble(pv,upper_warning_limit); + bitSet->set(pv->getFieldOffset()); + } + if(caValueAlarm.lower_warning_limit!=lower_warning_limit) { + caValueAlarm.lower_warning_limit = lower_warning_limit; + PVScalarPtr pv = pvValueAlarm->getSubField("lowWarningLimit"); + convert->fromDouble(pv,lower_warning_limit); + bitSet->set(pv->getFieldOffset()); + } + if(caValueAlarm.lower_alarm_limit!=lower_alarm_limit) { + caValueAlarm.lower_alarm_limit = lower_alarm_limit; + PVScalarPtr pv = pvValueAlarm->getSubField("lowAlarmLimit"); + convert->fromDouble(pv,lower_alarm_limit); + bitSet->set(pv->getFieldOffset()); + } } if(firstTime) { firstTime = false; @@ -786,6 +662,23 @@ Status DbdToPv::getFromDBD( return Status::Ok; } +template +const void * put_DBRScalar(dbrT *val,PVScalar::shared_pointer const & pvScalar) +{ + std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvScalar); + *val = value->get(); + return val; +} + +template +const void * put_DBRScalarArray(unsigned long*count, PVScalarArray::shared_pointer const & pvArray) +{ + std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvArray); + *count = value->getLength(); + return value->view().data(); +} + + Status DbdToPv::putToDBD( CAChannelPtr const & caChannel, PVStructurePtr const & pvStructure, @@ -794,28 +687,21 @@ Status DbdToPv::putToDBD( chid channelID = caChannel->getChannelID(); const void *pValue = NULL; unsigned long count = 1; - dbr_enum_t indexvalue(0); + char *ca_stringBuffer(0); dbr_char_t bvalue(0); dbr_short_t svalue(0); - dbr_long_t ivalue(0); + dbr_long_t lvalue(0); dbr_float_t fvalue(0); dbr_double_t dvalue(0); - char *ca_stringBuffer(0); - - - switch(caValueType) { - case DBR_ENUM: - { - indexvalue = pvStructure->getSubField("value.index")->get(); - pValue = &indexvalue; - break; - } - case DBR_STRING: - { - if(isArray) { + if(isArray) { + PVScalarArrayPtr pvValue = pvStructure->getSubField("value"); + switch(caValueType) { + case DBR_STRING: + { PVStringArrayPtr pvValue = pvStructure->getSubField("value"); count = pvValue->getLength(); if(count<1) break; + if(count>maxElements) count = maxElements; int nbytes = count*MAX_STRING_SIZE; ca_stringBuffer = new char[nbytes]; memset(ca_stringBuffer, 0, nbytes); @@ -829,78 +715,51 @@ Status DbdToPv::putToDBD( memcpy(pnext, value.c_str(), len); pnext += MAX_STRING_SIZE; } - } else { - pValue = pvStructure->getSubField("value")->get().c_str(); + break; } - break; - } - case DBR_CHAR: - { - if(isArray) { - PVByteArrayPtr pvValue = pvStructure->getSubField("value"); - count = pvValue->getLength(); - pValue = pvValue->view().data(); - } else { - bvalue = pvStructure->getSubField("value")->get(); - pValue = &bvalue; - } - break; - } - case DBR_SHORT: - { - if(isArray) { - PVShortArrayPtr pvValue = pvStructure->getSubField("value"); - count = pvValue->getLength(); - pValue = pvValue->view().data(); - } else { - svalue = pvStructure->getSubField("value")->get(); - pValue = &svalue; - } - break; - } - case DBR_LONG: - { - if(isArray) { - PVIntArrayPtr pvValue = pvStructure->getSubField("value"); - count = pvValue->getLength(); - pValue = pvValue->view().data(); - } else { - ivalue = pvStructure->getSubField("value")->get(); - pValue = &ivalue; - } - break; - } - case DBR_FLOAT: - { - if(isArray) { - PVFloatArrayPtr pvValue = pvStructure->getSubField("value"); - count = pvValue->getLength(); - pValue = pvValue->view().data(); - } else { - fvalue = pvStructure->getSubField("value")->get(); - pValue = &fvalue; - } - break; - } - case DBR_DOUBLE: - { - if(isArray) { - PVDoubleArrayPtr pvValue = pvStructure->getSubField("value"); - count = pvValue->getLength(); - pValue = pvValue->view().data(); - } else { - dvalue = pvStructure->getSubField("value")->get(); - pValue = &dvalue; - } - break; - } - default: - Status errorStatus( - Status::STATUSTYPE_ERROR, string("DbdToPv::FromDBD logic error")); - return errorStatus; - } - int result = 0; - if(block) { + case DBR_CHAR: + pValue = put_DBRScalarArray(&count,pvValue); + break; + case DBR_SHORT: + pValue = put_DBRScalarArray(&count,pvValue); + break; + case DBR_LONG: + pValue = put_DBRScalarArray(&count,pvValue); + break; + case DBR_FLOAT: + pValue = put_DBRScalarArray(&count,pvValue); + break; + case DBR_DOUBLE: + pValue = put_DBRScalarArray(&count,pvValue); + break; + default: + Status errorStatus( + Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD logic error")); + return errorStatus; + } + } else { + PVScalarPtr pvValue = pvStructure->getSubField("value"); + switch(caValueType) { + case DBR_ENUM: + { + dbr_enum_t indexvalue = pvStructure->getSubField("value.index")->get(); + pValue = &indexvalue; + break; + } + case DBR_STRING: pValue = pvStructure->getSubField("value")->get().c_str(); break; + case DBR_CHAR: pValue = put_DBRScalar(&bvalue,pvValue); break; + case DBR_SHORT: pValue = put_DBRScalar(&svalue,pvValue); break; + case DBR_LONG: pValue = put_DBRScalar(&lvalue,pvValue); break; + case DBR_FLOAT: pValue = put_DBRScalar(&fvalue,pvValue); break; + case DBR_DOUBLE: pValue = put_DBRScalar(&dvalue,pvValue); break; + default: + Status errorStatus( + Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD logic error")); + return errorStatus; + } + } + int result = 0; + if(block) { caChannel->attachContext(); result = ca_array_put_callback(caValueType,count,channelID,pValue,putHandler,this); if(result==ECA_NORMAL) { @@ -910,15 +769,15 @@ Status DbdToPv::putToDBD( } return putStatus; } - } else { + } else { caChannel->attachContext(); result = ca_array_put(caValueType,count,channelID,pValue); ca_flush_io(); - } - if(ca_stringBuffer!=NULL) delete[] ca_stringBuffer; - if(result==ECA_NORMAL) return Status::Ok; - Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(result))); - return errorStatus; + } + if(ca_stringBuffer!=NULL) delete[] ca_stringBuffer; + if(result==ECA_NORMAL) return Status::Ok; + Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(result))); + return errorStatus; } void DbdToPv::putDone(struct event_handler_args &args) diff --git a/src/ca/dbdToPv.h b/src/ca/dbdToPv.h index 72d63e3..fcb1d62 100644 --- a/src/ca/dbdToPv.h +++ b/src/ca/dbdToPv.h @@ -73,17 +73,11 @@ class DbdToPv { public: POINTER_DEFINITIONS(DbdToPv); - /** @brief - * - */ static DbdToPvPtr create( CAChannelPtr const & caChannel, epics::pvData::PVStructurePtr const & pvRequest, IOType ioType ); - /** @brief - * - */ epics::pvData::PVStructurePtr createPVStructure(); chtype getRequestType(); epics::pvData::Status getFromDBD( @@ -100,10 +94,8 @@ public: void descriptionConnected(struct connection_handler_args args); void getDescriptionDone(struct event_handler_args &args); void putDone(struct event_handler_args &args); - private: DbdToPv(IOType ioType); - void activate( CAChannelPtr const & caChannel, epics::pvData::PVStructurePtr const & pvRequest @@ -119,6 +111,7 @@ private: bool firstTime; chtype caValueType; chtype caRequestType; + unsigned long maxElements; epicsTimeStamp caTimeStamp; CaAlarm caAlarm; CaDisplay caDisplay;