From 71303063a5923afd5e32edbb0a75660057b37209 Mon Sep 17 00:00:00 2001 From: mrkraimer Date: Sat, 31 Mar 2018 06:46:25 -0400 Subject: [PATCH] redo conversion between DBD and pvData --- src/ca/Makefile | 3 +- src/ca/caChannel.cpp | 1331 ++++------------------------------------- src/ca/caChannel.h | 46 +- src/ca/caProvider.cpp | 2 +- src/ca/caStatus.cpp | 69 --- src/ca/dbdToPv.cpp | 926 ++++++++++++++++++++++++++++ src/ca/dbdToPv.h | 138 +++++ src/ca/pv/caStatus.h | 29 - 8 files changed, 1208 insertions(+), 1336 deletions(-) delete mode 100644 src/ca/caStatus.cpp create mode 100644 src/ca/dbdToPv.cpp create mode 100644 src/ca/dbdToPv.h delete mode 100644 src/ca/pv/caStatus.h diff --git a/src/ca/Makefile b/src/ca/Makefile index bc376f0..d2b4d6d 100644 --- a/src/ca/Makefile +++ b/src/ca/Makefile @@ -11,10 +11,9 @@ SHRLIB_VERSION ?= $(EPICS_PVA_MAJOR_VERSION).$(EPICS_PVA_MINOR_VERSION).$(EPICS_ LIB_SYS_LIBS_WIN32 += ws2_32 INC += pv/caProvider.h -INC += pv/caStatus.h pvAccessCA_SRCS += caProvider.cpp pvAccessCA_SRCS += caChannel.cpp -pvAccessCA_SRCS += caStatus.cpp +pvAccessCA_SRCS += dbdToPv.cpp include $(TOP)/configure/RULES diff --git a/src/ca/caChannel.cpp b/src/ca/caChannel.cpp index f496afe..21ed1e8 100644 --- a/src/ca/caChannel.cpp +++ b/src/ca/caChannel.cpp @@ -14,7 +14,6 @@ #define epicsExportSharedSymbols #include "caChannel.h" -#include using namespace epics::pvData; using std::string; @@ -56,248 +55,11 @@ static void ca_connection_handler(struct connection_handler_args args) } } - -static ScalarType dbr2ST[] = -{ - pvString, // DBR_STRING = 0 - pvShort, // DBR_SHORT. DBR_INT = 1 - pvFloat, // DBR_FLOAT = 2 - static_cast(-1), // DBR_ENUM = 3 - pvByte, // DBR_CHAR = 4 - pvInt, // DBR_LONG = 5 - pvDouble // DBR_DOUBLE = 6 -}; - -static Structure::const_shared_pointer createStructure(CAChannel::shared_pointer const & channel, string const & properties) -{ - StandardFieldPtr standardField = getStandardField(); - Structure::const_shared_pointer structure; - - chtype channelType = channel->getNativeType(); - if (channelType != DBR_ENUM) - { - ScalarType st = dbr2ST[channelType]; - structure = (channel->getElementCount() > 1) ? - standardField->scalarArray(st, properties) : - standardField->scalar(st, properties); - } - else - { - // NOTE: enum arrays not supported - structure = standardField->enumerated(properties); - } - - return structure; -} - -static void ca_get_labels_handler(struct event_handler_args args) -{ - - if (args.status == ECA_NORMAL) - { - const dbr_gr_enum* dbr_enum_p = static_cast(args.dbr); - - PVStringArray* labelsArray = static_cast(args.usr); - if (labelsArray) - { - PVStringArray::svector labels(labelsArray->reuse()); - labels.resize(dbr_enum_p->no_str); - std::copy(dbr_enum_p->strs, dbr_enum_p->strs + dbr_enum_p->no_str, labels.begin()); - labelsArray->replace(freeze(labels)); - } - } - else - { - string mess("ca_get_labels_handler "); - mess += ca_message(args.status); - throw std::runtime_error(mess); - } -} - -// Filter out unrequested fields from a source structure according to a -// structure conforming to the format of the "field" field of a pvRequest, -// preserving type ids of unchanged structures. If ntTop is true also preserve -// type id if none of the deleted top-level subfields are the value field. -static StructureConstPtr refineStructure(StructureConstPtr const & source, - StructureConstPtr const & requestedFields, bool ntTop) -{ - if (requestedFields.get() == NULL || requestedFields->getNumberFields() == 0) - return source; - - FieldBuilderPtr builder = getFieldCreate()->createFieldBuilder(); - bool addId = true; - - FieldConstPtrArray fields = source->getFields(); - StringArray names = source->getFieldNames(); - size_t i = 0; - for (FieldConstPtrArray::const_iterator it = fields.begin(); it != fields.end(); ++it) - { - FieldConstPtr field = *it; - const std::string & name = names[i++]; - FieldConstPtr reqField = requestedFields->getField(name); - if (reqField.get()) - { - if (field->getType() != structure || (reqField->getType() != structure)) - builder->add(name,field); - else - { - StructureConstPtr substruct = - std::tr1::dynamic_pointer_cast(field); - - StructureConstPtr reqSubstruct = - std::tr1::dynamic_pointer_cast(reqField); - - StructureConstPtr nested = refineStructure(substruct, reqSubstruct, false); - builder->add(name,nested); - if (nested->getID() != substruct->getID()) - addId = false; - } - } - else if (!ntTop || name == "value") - addId = false; - } - if (addId) - builder->setId(source->getID()); - return builder->createStructure(); -} - -static PVStructure::shared_pointer createPVStructure(CAChannel::shared_pointer const & channel, string const & properties, PVStructurePtr pvRequest) -{ - StructureConstPtr unrefinedStructure = createStructure(channel, properties); - - PVStructurePtr fieldPVStructure = pvRequest->getSubField("field"); - StructureConstPtr finalStructure = fieldPVStructure.get() ? - refineStructure(unrefinedStructure, fieldPVStructure->getStructure(),true) : - unrefinedStructure; - - PVStructure::shared_pointer pvStructure = getPVDataCreate()->createPVStructure(finalStructure); - if (channel->getNativeType() == DBR_ENUM) - { - PVScalarArrayPtr pvScalarArray = pvStructure->getSubField("value.choices"); - - // TODO avoid getting labels if DBR_GR_ENUM or DBR_CTRL_ENUM is used in subsequent get - int result = ca_array_get_callback( - DBR_GR_ENUM, 1, channel->getChannelID(), ca_get_labels_handler, pvScalarArray.get()); - if (result == ECA_NORMAL) - { - result = ca_flush_io(); - // NOTE: we do not wait here, since all subsequent request (over TCP) is serialized - // and will guarantee that ca_get_labels_handler is called first - } - if (result != ECA_NORMAL){ - string mess(channel->getChannelName() + "PVStructure::shared_pointer createPVStructure "); - mess += "failed to get labels for enum "; - throw std::runtime_error(mess); - } - } - return pvStructure; -} - -static PVStructure::shared_pointer createPVStructure(CAChannel::shared_pointer const & channel, chtype dbrType, PVStructurePtr pvRequest) -{ - // Match to closest DBR type - // NOTE: value is always there - string properties; - bool isArray = channel->getElementCount() > 1; - if (dbrType >= DBR_CTRL_STRING) // 28 - { - if (dbrType != DBR_CTRL_STRING && dbrType != DBR_CTRL_ENUM) - { - if (isArray) - properties = "value,alarm,display"; - else - properties = "value,alarm,display,valueAlarm,control"; - } - else - properties = "value,alarm"; - } - else if (dbrType >= DBR_GR_STRING) // 21 - { - if (dbrType != DBR_GR_STRING && dbrType != DBR_GR_ENUM) - { - if (isArray) - properties = "value,alarm,display"; - else - properties = "value,alarm,display,valueAlarm"; - } - else - properties = "value,alarm"; - } - else if (dbrType >= DBR_TIME_STRING) // 14 - properties = "value,alarm,timeStamp"; - else if (dbrType >= DBR_STS_STRING) // 7 - properties = "value,alarm"; - else - properties = "value"; - - return createPVStructure(channel, properties, pvRequest); -} - - void CAChannel::connected() { if(DEBUG_LEVEL>0) { cout<< "CAChannel::connected " << channelName << endl; } - std::queue putQ; - std::queue getQ; - std::queue monitorQ; - { - Lock lock(requestsMutex); - // we assume array if element count > 1 - elementCount = ca_element_count(channelID); - channelType = ca_field_type(channelID); - bool isArray = elementCount > 1; - - // no valueAlarm and control,display for non-numeric type - // no control,display for numeric arrays - string allProperties = - (channelType != DBR_STRING && channelType != DBR_ENUM) ? - isArray ? - "value,timeStamp,alarm,display" : - "value,timeStamp,alarm,display,valueAlarm,control" : - "value,timeStamp,alarm"; - Structure::const_shared_pointer structure = createStructure( - shared_from_this(), allProperties); - - // TODO we need only Structure here - this->structure = structure; - - std::vector::const_iterator getiter; - for (getiter = getList.begin(); getiter != getList.end(); ++getiter) { - CAChannelGetPtr temp = (*getiter).lock(); - if(!temp) continue; - getQ.push(temp); - } - std::vector::const_iterator putiter; - for (putiter = putList.begin(); putiter != putList.end(); ++putiter) { - CAChannelPutPtr temp = (*putiter).lock(); - if(!temp) continue; - putQ.push(temp); - } - std::vector::const_iterator monitoriter; - for (monitoriter = monitorList.begin(); monitoriter != monitorList.end(); ++monitoriter) { - CAChannelMonitorPtr temp = (*monitoriter).lock(); - if(!temp) continue; - monitorQ.push(temp); - } - } - while(!putQ.empty()) { - putQ.front()->channelCreated(Status::Ok,shared_from_this()); - putQ.pop(); - } - while(!getQ.empty()) { - getQ.front()->channelCreated(Status::Ok,shared_from_this()); - getQ.pop(); - } - while(!monitorQ.empty()) { - monitorQ.front()->channelCreated(Status::Ok,shared_from_this()); - monitorQ.pop(); - } - while(!getFieldQueue.empty()) { - getFieldQueue.front()->callRequester(shared_from_this()); - getFieldQueue.pop(); - } while(!putQueue.empty()) { putQueue.front()->activate(); putQueue.pop(); @@ -322,41 +84,17 @@ void CAChannel::disconnected() if(DEBUG_LEVEL>0) { cout<< "CAChannel::disconnected " << channelName << endl; } - std::queue putQ; - std::queue getQ; - std::queue monitorQ; - { - Lock lock(requestsMutex); - std::vector::const_iterator getiter; - for (getiter = getList.begin(); getiter != getList.end(); ++getiter) { - CAChannelGetPtr temp = (*getiter).lock(); - if(!temp) continue; - getQ.push(temp); - } - std::vector::const_iterator putiter; - for (putiter = putList.begin(); putiter != putList.end(); ++putiter) { - CAChannelPutPtr temp = (*putiter).lock(); - if(!temp) continue; - putQ.push(temp); - } - std::vector::const_iterator monitoriter; - for (monitoriter = monitorList.begin(); monitoriter != monitorList.end(); ++monitoriter) { - CAChannelMonitorPtr temp = (*monitoriter).lock(); - if(!temp) continue; - monitorQ.push(temp); - } + while(!putQueue.empty()) { + putQueue.front()->channelDisconnect(false); + putQueue.pop(); } - while(!putQ.empty()) { - putQ.front()->channelDisconnect(false); - putQ.pop(); + while(!getQueue.empty()) { + getQueue.front()->channelDisconnect(false); + getQueue.pop(); } - while(!getQ.empty()) { - getQ.front()->channelDisconnect(false); - getQ.pop(); - } - while(!monitorQ.empty()) { - monitorQ.front()->channelDisconnect(false); - monitorQ.pop(); + while(!monitorQueue.empty()) { + monitorQueue.front()->channelDisconnect(false); + monitorQueue.pop(); } ChannelRequester::shared_pointer req(channelRequester.lock()); if(req) { @@ -374,8 +112,6 @@ CAChannel::CAChannel(std::string const & _channelName, channelProvider(_channelProvider), channelRequester(_channelRequester), channelID(0), - channelType(0), - elementCount(0), channelCreated(false) { if(DEBUG_LEVEL>0) { @@ -430,7 +166,10 @@ void CAChannel::disconnectChannel() channelCreated = false; } /* Clear CA Channel */ - attachContext(); + CAChannelProviderPtr provider(channelProvider.lock()); + if(provider) { + std::tr1::static_pointer_cast(provider)->attachContext(); + } int result = ca_clear_channel(channelID); if (result == ECA_NORMAL) return; string mess("CAChannel::disconnectChannel() "); @@ -491,24 +230,6 @@ chid CAChannel::getChannelID() return channelID; } - -chtype CAChannel::getNativeType() -{ - return channelType; -} - - -unsigned CAChannel::getElementCount() -{ - return elementCount; -} - -Structure::const_shared_pointer CAChannel::getStructure() -{ - return structure; -} - - std::tr1::shared_ptr CAChannel::getProvider() { return channelProvider.lock(); @@ -676,7 +397,10 @@ void CAChannelGetField::callRequester(CAChannelPtr const & caChannel) } GetFieldRequester::shared_pointer requester(getFieldRequester.lock()); if(!requester) return; - epics::pvData::Structure::const_shared_pointer structure(caChannel->getStructure()); + PVStructurePtr pvRequest(createRequest("")); + DbdToPvPtr dbdToPv = DbdToPv::create(caChannel,pvRequest,getIO); + PVStructurePtr pvStructure = dbdToPv->createPVStructure(); + epics::pvData::Structure::const_shared_pointer structure(pvStructure->getStructure()); Field::const_shared_pointer field = subField.empty() ? std::tr1::static_pointer_cast(structure) : @@ -700,42 +424,11 @@ void CAChannel::attachContext() CAChannelProviderPtr provider(channelProvider.lock()); if(provider) { std::tr1::static_pointer_cast(provider)->attachContext(); + return; } -} - -static chtype getDBRType(PVStructure::shared_pointer const & pvRequest, chtype nativeType) -{ - // get "field" sub-structure - PVStructure::shared_pointer fieldSubField = - std::tr1::dynamic_pointer_cast(pvRequest->getSubField("field")); - if (!fieldSubField) - fieldSubField = pvRequest; - Structure::const_shared_pointer fieldStructure = fieldSubField->getStructure(); - - // no fields - if (fieldStructure->getNumberFields() == 0) - { - return static_cast(static_cast(nativeType) + DBR_TIME_STRING); - } - // control -> DBR_CTRL_ - if (fieldStructure->getField("control")) - return static_cast(static_cast(nativeType) + DBR_CTRL_STRING); - - // display/valueAlarm -> DBR_GR_ - if (fieldStructure->getField("display") || fieldStructure->getField("valueAlarm")) - return static_cast(static_cast(nativeType) + DBR_GR_STRING); - - // timeStamp -> DBR_TIME_ - // NOTE: that only DBR_TIME_ type holds timestamp, therefore if you request for - // the fields above, you will never get timestamp - if (fieldStructure->getField("timeStamp")) - return static_cast(static_cast(nativeType) + DBR_TIME_STRING); - - // alarm -> DBR_STS_ - if (fieldStructure->getField("alarm")) - return static_cast(static_cast(nativeType) + DBR_STS_STRING); - - return nativeType; + string mess("CAChannel::attachContext "); + mess += getChannelName(); + throw std::runtime_error(mess); } size_t CAChannelGet::num_instances; @@ -745,23 +438,20 @@ CAChannelGetPtr CAChannelGet::create( ChannelGetRequester::shared_pointer const & channelGetRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { + if(DEBUG_LEVEL>0) { + cout << "CAChannelGet::create " << channel->getChannelName() << endl; + } return CAChannelGetPtr(new CAChannelGet(channel, channelGetRequester, pvRequest)); } - CAChannelGet::CAChannelGet(CAChannel::shared_pointer const & channel, ChannelGetRequester::shared_pointer const & channelGetRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) : channel(channel), channelGetRequester(channelGetRequester), - pvRequest(pvRequest), - firstTime(true) -{ - if(DEBUG_LEVEL>0) { - cout << "CAChannelGet::CAChannelGet() " << channel->getChannelName() << endl; - } -} + pvRequest(pvRequest) +{} CAChannelGet::~CAChannelGet() { @@ -770,46 +460,20 @@ CAChannelGet::~CAChannelGet() } } +void CAChannelGet::channelCreated(const epics::pvData::Status& s,Channel::shared_pointer const & c) +{} + void CAChannelGet::activate() { ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock()); - if(DEBUG_LEVEL>0) { - std::cout << "CAChannelGet::activate " << channel->getChannelName() << " requester "<getNativeType()); - pvStructure = createPVStructure(channel, getType, pvRequest); + if(DEBUG_LEVEL>0) { + std::cout << "CAChannelGet::activate " << channel->getChannelName() << endl; + } + dbdToPv = DbdToPv::create(channel,pvRequest,getIO); + pvStructure = dbdToPv->createPVStructure(); bitSet = BitSetPtr(new BitSet(pvStructure->getStructure()->getNumberFields())); - pvCopy = PVCopy::create( - createPVStructure(channel, getType, pvRequest), - CreateRequest::create()->createRequest("field()"), - ""); channel->addChannelGet(shared_from_this()); - if(channel->getConnectionState()==Channel::CONNECTED) { - EXCEPTION_GUARD(getRequester->channelGetConnect(Status::Ok, shared_from_this(), - pvStructure->getStructure())); - } -} - -void CAChannelGet::channelCreated(const Status& status,Channel::shared_pointer const & cl) -{ - if(DEBUG_LEVEL>0) { - std::cout << "CAChannelGet::channelCreated " << channel->getChannelName() << endl; - } - firstTime = true; - ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock()); - if(!getRequester) return; - chtype newType = getDBRType(pvRequest, channel->getNativeType()); - if(newType!=getType) { - getType = getDBRType(pvRequest, channel->getNativeType()); - pvStructure = createPVStructure(channel, getType, pvRequest); - bitSet = BitSetPtr(new BitSet(pvStructure->getStructure()->getNumberFields())); - pvCopy = PVCopy::create( - createPVStructure(channel, getType, pvRequest), - CreateRequest::create()->createRequest("field()"), - ""); - } EXCEPTION_GUARD(getRequester->channelGetConnect(Status::Ok, shared_from_this(), pvStructure->getStructure())); } @@ -818,14 +482,9 @@ void CAChannelGet::channelStateChange( Channel::shared_pointer const & channel, Channel::ConnectionState connectionState) { - if(DEBUG_LEVEL>0) { - std::cout << "CAChannelGet::channelStateChange " << channel->getChannelName() << endl; - } - ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock()); - if(!getRequester) return; - if(connectionState==Channel::DISCONNECTED || connectionState==Channel::DESTROYED) { - EXCEPTION_GUARD(getRequester->channelDisconnect(connectionState==Channel::DESTROYED);) - } + string mess("CAChannelGet::channelStateChange was called "); + mess += channel->getChannelName(); + throw std::runtime_error(mess); } void CAChannelGet::channelDisconnect(bool destroy) @@ -836,6 +495,7 @@ void CAChannelGet::channelDisconnect(bool destroy) ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock()); if(!getRequester) return; EXCEPTION_GUARD(getRequester->channelDisconnect(destroy);) + if(!destroy) channel->addChannelGet(shared_from_this()); } /* --------------- epics::pvAccess::ChannelGet --------------- */ @@ -848,394 +508,21 @@ static void ca_get_handler(struct event_handler_args args) channelGet->getDone(args); } -typedef void (*copyDBRtoPVStructure)(const void * from, unsigned count, PVStructure::shared_pointer const & to); - - -// template -template -void copy_DBR(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - if (count == 1) - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - if (value.get()) value->put(static_cast(dbr)[0]); - } - else - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - if (value.get()) - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - typename aF::svector temp(value->reuse()); - temp.resize(count); - std::copy(static_cast(dbr), static_cast(dbr) + count, temp.begin()); - value->replace(freeze(temp)); - } - } -} - -#if defined(__vxworks) || defined(__rtems__) -// dbr_long_t is defined as "int", pvData uses int32 which can be defined as "long int" (32-bit) -// template -template<> -void copy_DBR(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - if (count == 1) - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - if (value.get()) value->put(static_cast(dbr)[0]); - } - else - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - if (value.get()) - { - PVIntArray::svector temp(value->reuse()); - temp.resize(count); - std::copy(static_cast(dbr), static_cast(dbr) + count, temp.begin()); - value->replace(freeze(temp)); - } - } -} -#endif - -// string specialization -template<> -void copy_DBR(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - if (count == 1) - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - if (value.get()) value->put(std::string(static_cast(dbr))); - } - else - { - std::tr1::shared_ptr value = pvStructure->getSubField("value"); - if (value.get()) - { - const dbr_string_t* dbrStrings = static_cast(dbr); - PVStringArray::svector sA(value->reuse()); - sA.resize(count); - std::copy(dbrStrings, dbrStrings + count, sA.begin()); - value->replace(freeze(sA)); - } - } -} - -// enum specialization -template<> -void copy_DBR(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - if (count == 1) - { - PVIntPtr value = pvStructure->getSubField("value.index"); - if (value.get()) value->put(static_cast(dbr)[0]); - } - else - { - // not supported - std::cerr << "caChannel: array of enums not supported" << std::endl; - } -} - -// template -template -void copy_DBR_STS(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - const T* data = static_cast(dbr); - - PVStructure::shared_pointer alarm = pvStructure->getSubField("alarm"); - if (alarm.get()) - { - PVIntPtr status = alarm->getSubField("status"); - if (status.get()) status->put(dbrStatus2alarmStatus[data->status]); - - PVIntPtr severity = alarm->getSubField("severity"); - if (severity.get()) severity->put(data->severity); - - PVStringPtr message = alarm->getSubField("message"); - if (message.get()) message->put(dbrStatus2alarmMessage[data->status]); - } - - copy_DBR(&data->value, count, pvStructure); -} - -// template -template -void copy_DBR_TIME(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - const T* data = static_cast(dbr); - - PVStructure::shared_pointer ts = pvStructure->getSubField("timeStamp"); - if (ts.get()) - { - epics::pvData::int64 spe = data->stamp.secPastEpoch; - spe += 7305*86400; - - PVLongPtr secondsPastEpoch = ts->getSubField("secondsPastEpoch"); - if (secondsPastEpoch.get()) secondsPastEpoch->put(spe); - - PVIntPtr nanoseconds = ts->getSubField("nanoseconds"); - if (nanoseconds.get()) nanoseconds->put(data->stamp.nsec); - } - - copy_DBR_STS(dbr, count, pvStructure); -} - - -template -void copy_format(const void * /*dbr*/, PVStructure::shared_pointer const & pvDisplayStructure) -{ - PVStringPtr format = pvDisplayStructure->getSubField("format"); - if (format.get()) format->put("%d"); -} - -#define COPY_FORMAT_FOR(T) \ -template <> \ -void copy_format(const void * dbr, PVStructure::shared_pointer const & pvDisplayStructure) \ -{ \ - const T* data = static_cast(dbr); \ -\ - if (data->precision) \ - { \ - char fmt[16]; \ - sprintf(fmt, "%%.%df", data->precision); \ - PVStringPtr format = pvDisplayStructure->getSubField("format");\ - if (format.get()) format->put(std::string(fmt));\ - } \ - else \ - { \ - PVStringPtr format = pvDisplayStructure->getSubField("format");\ - if (format.get()) format->put("%f");\ - } \ -} - -COPY_FORMAT_FOR(dbr_gr_float) -COPY_FORMAT_FOR(dbr_ctrl_float) -COPY_FORMAT_FOR(dbr_gr_double) -COPY_FORMAT_FOR(dbr_ctrl_double) - -#undef COPY_FORMAT_FOR - -// template -template -void copy_DBR_GR(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - const T* data = static_cast(dbr); - - PVStructurePtr alarm = pvStructure->getSubField("alarm"); - if (alarm.get()) - { - PVIntPtr status = alarm->getSubField("status"); - if (status.get()) status->put(dbrStatus2alarmStatus[data->status]); - - PVIntPtr severity = alarm->getSubField("severity"); - if (severity.get()) severity->put(data->severity); - - PVStringPtr message = alarm->getSubField("message"); - if (message.get()) message->put(dbrStatus2alarmMessage[data->status]); - } - - PVStructurePtr disp = pvStructure->getSubField("display"); - if (disp.get()) - { - PVStringPtr units = disp->getSubField("units"); - if (units.get()) units->put(std::string(data->units)); - - PVDoublePtr limitHigh = disp->getSubField("limitHigh"); - if (limitHigh.get()) limitHigh->put(data->upper_disp_limit); - - PVDoublePtr limitLow = disp->getSubField("limitLow"); - if (limitLow.get()) limitLow->put(data->lower_disp_limit); - - copy_format(dbr, disp); - } - - PVStructurePtr va = pvStructure->getSubField("valueAlarm"); - if (va.get()) - { - std::tr1::shared_ptr highAlarmLimit = va->getSubField("highAlarmLimit"); - if (highAlarmLimit.get()) highAlarmLimit->put(data->upper_alarm_limit); - - std::tr1::shared_ptr highWarningLimit = va->getSubField("highWarningLimit"); - if (highWarningLimit.get()) highWarningLimit->put(data->upper_warning_limit); - - std::tr1::shared_ptr lowWarningLimit = va->getSubField("lowWarningLimit"); - if (lowWarningLimit.get()) lowWarningLimit->put(data->lower_warning_limit); - - std::tr1::shared_ptr lowAlarmLimit = va->getSubField("lowAlarmLimit"); - if (lowAlarmLimit.get()) lowAlarmLimit->put(data->lower_alarm_limit); - } - - copy_DBR(&data->value, count, pvStructure); -} - -// enum specialization -template<> -void copy_DBR_GR -(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - const dbr_gr_enum* data = static_cast(dbr); - - copy_DBR_STS(data, count, pvStructure); -} - - -// template -template -void copy_DBR_CTRL(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - const T* data = static_cast(dbr); - - PVStructure::shared_pointer alarm = pvStructure->getSubField("alarm"); - if (alarm.get()) - { - PVIntPtr status = alarm->getSubField("status"); - if (status.get()) status->put(dbrStatus2alarmStatus[data->status]); - - PVIntPtr severity = alarm->getSubField("severity"); - if (severity.get()) severity->put(data->severity); - - PVStringPtr message = alarm->getSubField("message"); - if (message.get()) message->put(dbrStatus2alarmMessage[data->status]); - } - - PVStructurePtr disp = pvStructure->getSubField("display"); - if (disp.get()) - { - PVStringPtr units = disp->getSubField("units"); - if (units.get()) units->put(std::string(data->units)); - - PVDoublePtr limitHigh = disp->getSubField("limitHigh"); - if (limitHigh.get()) limitHigh->put(data->upper_disp_limit); - - PVDoublePtr limitLow = disp->getSubField("limitLow"); - if (limitLow.get()) limitLow->put(data->lower_disp_limit); - - copy_format(dbr, disp); - } - - PVStructurePtr va = pvStructure->getSubField("valueAlarm"); - if (va.get()) - { - std::tr1::shared_ptr highAlarmLimit = va->getSubField("highAlarmLimit"); - if (highAlarmLimit.get()) highAlarmLimit->put(data->upper_alarm_limit); - - std::tr1::shared_ptr highWarningLimit = va->getSubField("highWarningLimit"); - if (highWarningLimit.get()) highWarningLimit->put(data->upper_warning_limit); - - std::tr1::shared_ptr lowWarningLimit = va->getSubField("lowWarningLimit"); - if (lowWarningLimit.get()) lowWarningLimit->put(data->lower_warning_limit); - - std::tr1::shared_ptr lowAlarmLimit = va->getSubField("lowAlarmLimit"); - if (lowAlarmLimit.get()) lowAlarmLimit->put(data->lower_alarm_limit); - } - - PVStructurePtr ctrl = pvStructure->getSubField("control"); - if (ctrl.get()) - { - PVDoublePtr limitHigh = ctrl->getSubField("limitHigh"); - if (limitHigh.get()) limitHigh->put(data->upper_ctrl_limit); - - PVDoublePtr limitLow = ctrl->getSubField("limitLow"); - if (limitLow.get()) limitLow->put(data->lower_ctrl_limit); - } - - copy_DBR(&data->value, count, pvStructure); -} - -// enum specialization -template<> -void copy_DBR_CTRL -(const void * dbr, unsigned count, PVStructure::shared_pointer const & pvStructure) -{ - const dbr_ctrl_enum* data = static_cast(dbr); - - copy_DBR_STS(data, count, pvStructure); -} - - -static copyDBRtoPVStructure copyFuncTable[] = -{ - copy_DBR, // DBR_STRING - copy_DBR, // DBR_INT, DBR_SHORT - copy_DBR, // DBR_FLOAT - copy_DBR, // DBR_ENUM - copy_DBR, // DBR_CHAR - copy_DBR, // DBR_LONG - copy_DBR, // DBR_DOUBLE - - copy_DBR_STS, // DBR_STS_STRING - copy_DBR_STS, // DBR_STS_INT, DBR_STS_SHORT - copy_DBR_STS, // DBR_STS_FLOAT - copy_DBR_STS, // DBR_STS_ENUM - copy_DBR_STS, // DBR_STS_CHAR - copy_DBR_STS, // DBR_STS_LONG - copy_DBR_STS, // DBR_STS_DOUBLE - - copy_DBR_TIME, // DBR_TIME_STRING - copy_DBR_TIME, // DBR_TIME_INT, DBR_TIME_SHORT - copy_DBR_TIME, // DBR_TIME_FLOAT - copy_DBR_TIME, // DBR_TIME_ENUM - copy_DBR_TIME, // DBR_TIME_CHAR - copy_DBR_TIME, // DBR_TIME_LONG - copy_DBR_TIME, // DBR_TIME_DOUBLE - - copy_DBR_STS, // DBR_GR_STRING -> DBR_STS_STRING - copy_DBR_GR, // DBR_GR_INT, DBR_GR_SHORT - copy_DBR_GR, // DBR_GR_FLOAT - copy_DBR_GR, // DBR_GR_ENUM - copy_DBR_GR, // DBR_GR_CHAR - copy_DBR_GR, // DBR_GR_LONG - copy_DBR_GR, // DBR_GR_DOUBLE - - copy_DBR_STS, // DBR_CTRL_STRING -> DBR_STS_STRING - copy_DBR_CTRL, // DBR_CTRL_INT, DBR_CTRL_SHORT - copy_DBR_CTRL, // DBR_CTRL_FLOAT - copy_DBR_CTRL, // DBR_CTRL_ENUM - copy_DBR_CTRL, // DBR_CTRL_CHAR - copy_DBR_CTRL, // DBR_CTRL_LONG - copy_DBR_CTRL // DBR_CTRL_DOUBLE -}; - } // namespace void CAChannelGet::getDone(struct event_handler_args &args) { if(DEBUG_LEVEL>1) { std::cout << "CAChannelGet::getDone " - << channel->getChannelName() - << " firstTime " << (firstTime ? "true" : "false") - << endl; + << channel->getChannelName() << endl; } + ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock()); if(!getRequester) return; - if (args.status == ECA_NORMAL) - { - copyDBRtoPVStructure copyFunc = copyFuncTable[getType]; - if (copyFunc) - copyFunc(args.dbr, args.count, pvStructure); - else - { - throw std::runtime_error("CAChannelGet::getDone no copy func implemented"); - } - pvCopy->updateMasterSetBitSet(pvStructure,bitSet); - if(firstTime) { - bitSet->clear(); - bitSet->set(0); - firstTime = false; - } - EXCEPTION_GUARD(getRequester->getDone(Status::Ok, shared_from_this(), pvStructure, bitSet)); - } - else - { - Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(args.status))); - EXCEPTION_GUARD(getRequester->getDone(errorStatus, shared_from_this(), - PVStructure::shared_pointer(), BitSet::shared_pointer())); - } + Status status = dbdToPv->getFromDBD(pvStructure,bitSet,args); + EXCEPTION_GUARD(getRequester->getDone(status, shared_from_this(), pvStructure, bitSet)); } - void CAChannelGet::get() { if(DEBUG_LEVEL>1) { @@ -1244,31 +531,22 @@ void CAChannelGet::get() ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock()); if(!getRequester) return; channel->attachContext(); - - /* - From R3.14.12 onwards ca_array_get_callback() replies will give a CA client application the current number - of elements in an array field, provided they specified an element count of zero in their original request. - The element count is passed in the callback argument structure. - Prior to R3.14.12 requesting zero elements in a ca_array_get_callback() call was illegal and would fail - immediately. - */ bitSet->clear(); - int result = ca_array_get_callback(getType, + int result = ca_array_get_callback(dbdToPv->getRequestType(), 0, channel->getChannelID(), ca_get_handler, this); if (result == ECA_NORMAL) { result = ca_flush_io(); } - if (result == ECA_NORMAL) return; - string mess("CAChannelGet::get "); - mess += ca_message(result); - throw std::runtime_error(mess); + if (result != ECA_NORMAL) + { + string mess("CAChannelGet::get "); + mess += channel->getChannelName() + " message " + ca_message(result); + throw std::runtime_error(mess); + } } - -/* --------------- epics::pvData::ChannelRequest --------------- */ - Channel::shared_pointer CAChannelGet::getChannel() { return channel; @@ -1282,26 +560,19 @@ void CAChannelGet::lastRequest() { } - +size_t CAChannelPut::num_instances; CAChannelPutPtr CAChannelPut::create( CAChannel::shared_pointer const & channel, ChannelPutRequester::shared_pointer const & channelPutRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { + if(DEBUG_LEVEL>0) { + cout << "CAChannelPut::create " << channel->getChannelName() << endl; + } return CAChannelPutPtr(new CAChannelPut(channel, channelPutRequester, pvRequest)); } - -CAChannelPut::~CAChannelPut() -{ - if(DEBUG_LEVEL>0) { - std::cout << "CAChannelPut::~CAChannelPut() " << channel->getChannelName() << endl; - } -} - -size_t CAChannelPut::num_instances; - CAChannelPut::CAChannelPut(CAChannel::shared_pointer const & channel, ChannelPutRequester::shared_pointer const & channelPutRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) @@ -1310,56 +581,34 @@ CAChannelPut::CAChannelPut(CAChannel::shared_pointer const & channel, channelPutRequester(channelPutRequester), pvRequest(pvRequest), block(false) +{} + +CAChannelPut::~CAChannelPut() { if(DEBUG_LEVEL>0) { - cout << "CAChannelPut::CAChannePut() " << channel->getChannelName() << endl; + std::cout << "CAChannelPut::~CAChannelPut() " << channel->getChannelName() << endl; } } +void CAChannelPut::channelCreated(const Status& status,Channel::shared_pointer const & c) +{} + void CAChannelPut::activate() { + ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); + if(!putRequester) return; if(DEBUG_LEVEL>0) { cout << "CAChannelPut::activate " << channel->getChannelName() << endl; } - ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); - if(!putRequester) return; - if(pvStructure) throw std::runtime_error("CAChannelPut::activate() was called twice"); - getType = getDBRType(pvRequest,channel->getNativeType()); - pvStructure = createPVStructure(channel, getType, pvRequest); + dbdToPv = DbdToPv::create(channel,pvRequest,putIO); + pvStructure = dbdToPv->createPVStructure(); bitSet = BitSetPtr(new BitSet(pvStructure->getStructure()->getNumberFields())); PVStringPtr pvString = pvRequest->getSubField("record._options.block"); if(pvString) { std::string val = pvString->get(); if(val.compare("true")==0) block = true; } - bitSet->set(pvStructure->getSubFieldT("value")->getFieldOffset()); channel->addChannelPut(shared_from_this()); - if(channel->getConnectionState()==Channel::CONNECTED) { - EXCEPTION_GUARD(putRequester->channelPutConnect(Status::Ok, shared_from_this(), - pvStructure->getStructure())); - } -} - - -void CAChannelPut::channelCreated(const Status& status,Channel::shared_pointer const & c) -{ - if(DEBUG_LEVEL>0) { - cout << "CAChannelPut::channelCreated " << channel->getChannelName() << endl; - } - ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); - if(!putRequester) return; - chtype newType = getDBRType(pvRequest, channel->getNativeType()); - if(newType!=getType) { - getType = getDBRType(pvRequest, channel->getNativeType()); - pvStructure = createPVStructure(channel, getType, pvRequest); - bitSet = BitSetPtr(new BitSet(pvStructure->getStructure()->getNumberFields())); - PVStringPtr pvString = pvRequest->getSubField("record._options.block"); - if(pvString) { - std::string val = pvString->get(); - if(val.compare("true")==0) block = true; - } - bitSet->set(0); - } EXCEPTION_GUARD(putRequester->channelPutConnect(Status::Ok, shared_from_this(), pvStructure->getStructure())); } @@ -1368,14 +617,9 @@ void CAChannelPut::channelStateChange( Channel::shared_pointer const & channel, Channel::ConnectionState connectionState) { - if(DEBUG_LEVEL>0) { - cout << "CAChannelPut::channelStateChange " << channel->getChannelName() << endl; - } - ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); - if(!putRequester) return; - if(connectionState==Channel::DISCONNECTED || connectionState==Channel::DESTROYED) { - EXCEPTION_GUARD(putRequester->channelDisconnect(connectionState==Channel::DESTROYED);) - } + string mess("CAChannelPut::channelStateChange was called "); + mess += channel->getChannelName(); + throw std::runtime_error(mess); } void CAChannelPut::channelDisconnect(bool destroy) @@ -1386,224 +630,21 @@ void CAChannelPut::channelDisconnect(bool destroy) ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); if(!putRequester) return; EXCEPTION_GUARD(putRequester->channelDisconnect(destroy);) + if(!destroy) channel->addChannelPut(shared_from_this()); } /* --------------- epics::pvAccess::ChannelPut --------------- */ namespace { -static void ca_put_handler(struct event_handler_args args) -{ - CAChannelPut *channelPut = static_cast(args.usr); - channelPut->putDone(args); -} - - static void ca_put_get_handler(struct event_handler_args args) { CAChannelPut *channelPut = static_cast(args.usr); channelPut->getDone(args); } -typedef int (*doPut)(CAChannel::shared_pointer const & channel, void *usrArg, PVStructure::shared_pointer const & from); - - -// template -template -int doPut_pvStructure(CAChannel::shared_pointer const & channel, void *usrArg, PVStructure::shared_pointer const & pvStructure) -{ - bool isScalarValue = pvStructure->getStructure()->getField("value")->getType() == scalar; - - if (isScalarValue) - { - std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvStructure->getSubFieldT("value")); - - pT val = value->get(); - int result = 0; - if(usrArg!=NULL) { - result = ca_array_put_callback(channel->getNativeType(), 1, - channel->getChannelID(), &val, - ca_put_handler, usrArg); - } else { - result = ca_array_put(channel->getNativeType(), 1, - channel->getChannelID(), &val); - } - - if (result == ECA_NORMAL) - { - ca_flush_io(); - } - - return result; - } - else - { - std::tr1::shared_ptr value = pvStructure->getSubFieldT("value"); - - const pT* val = value->view().data(); - int result = 0; - if(usrArg!=NULL) { - result = ca_array_put_callback(channel->getNativeType(), - static_cast(value->getLength()), - channel->getChannelID(), val, - ca_put_handler, usrArg); - } else { - result = ca_array_put(channel->getNativeType(), - static_cast(value->getLength()), - channel->getChannelID(), val); - } - if (result == ECA_NORMAL) - { - ca_flush_io(); - } - - return result; - } -} - -// string specialization -template<> -int doPut_pvStructure(CAChannel::shared_pointer const & channel, void *usrArg, PVStructure::shared_pointer const & pvStructure) -{ - bool isScalarValue = pvStructure->getStructure()->getField("value")->getType() == scalar; - - if (isScalarValue) - { - std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvStructure->getSubFieldT("value")); - - string val = value->get(); - int result = 0; - if(usrArg!=NULL) { - result = ca_array_put_callback( - channel->getNativeType(), 1, - channel->getChannelID(), val.c_str(), - ca_put_handler, usrArg); - } else { - result = ca_array_put( - channel->getNativeType(), 1, - channel->getChannelID(), val.c_str()); - } - if (result == ECA_NORMAL) - { - ca_flush_io(); - } - - return result; - } - else - { - std::tr1::shared_ptr value = pvStructure->getSubFieldT("value"); - - PVStringArray::const_svector stringArray(value->view()); - - size_t arraySize = stringArray.size(); - size_t ca_stringBufferSize = arraySize * MAX_STRING_SIZE; - char* ca_stringBuffer = new char[ca_stringBufferSize]; - memset(ca_stringBuffer, 0, ca_stringBufferSize); - - char *p = ca_stringBuffer; - for(size_t i = 0; i < arraySize; i++) - { - string value = stringArray[i]; - size_t len = value.length(); - if (len >= MAX_STRING_SIZE) - len = MAX_STRING_SIZE - 1; - memcpy(p, value.c_str(), len); - p += MAX_STRING_SIZE; - } - - int result = 0; - if(usrArg!=NULL) { - result = ca_array_put_callback( - channel->getNativeType(), arraySize, - channel->getChannelID(), ca_stringBuffer, - ca_put_handler, usrArg); - } else { - result = ca_array_put( - channel->getNativeType(), arraySize, - channel->getChannelID(), ca_stringBuffer); - } - delete[] ca_stringBuffer; - - if (result == ECA_NORMAL) - { - ca_flush_io(); - } - - return result; - } -} - -// enum specialization -template<> -int doPut_pvStructure(CAChannel::shared_pointer const & channel, void *usrArg, PVStructure::shared_pointer const & pvStructure) -{ - bool isScalarValue = pvStructure->getStructure()->getField("value")->getType() == structure; - - if (isScalarValue) - { - std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvStructure->getSubFieldT("value.index")); - - dbr_enum_t val = value->get(); - int result = 0; - if(usrArg!=NULL) { - result = ca_array_put_callback( - channel->getNativeType(), 1, - channel->getChannelID(), &val, - ca_put_handler, usrArg); - } else { - result = ca_array_put( - channel->getNativeType(), 1, - channel->getChannelID(), &val); - } - if (result == ECA_NORMAL) - { - ca_flush_io(); - } - - return result; - } - else - { - // no enum arrays in V3 - return ECA_NOSUPPORT; - } -} - -static doPut doPutFuncTable[] = -{ - doPut_pvStructure, // DBR_STRING - doPut_pvStructure, // DBR_INT, DBR_SHORT - doPut_pvStructure, // DBR_FLOAT - doPut_pvStructure, // DBR_ENUM - doPut_pvStructure, // DBR_CHAR -#if defined(__vxworks) || defined(__rtems__) - doPut_pvStructure, // DBR_LONG -#else - doPut_pvStructure, // DBR_LONG -#endif - doPut_pvStructure, // DBR_DOUBLE -}; - } // namespace -void CAChannelPut::putDone(struct event_handler_args &args) -{ - if(DEBUG_LEVEL>1) { - cout << "CAChannelPut::putDone " << channel->getChannelName() << endl; - } - ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); - if(!putRequester) return; - if (args.status == ECA_NORMAL) - { - EXCEPTION_GUARD(putRequester->putDone(Status::Ok, shared_from_this())); - } - else - { - Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(args.status))); - EXCEPTION_GUARD(putRequester->putDone(errorStatus, shared_from_this())); - } -} void CAChannelPut::put(PVStructure::shared_pointer const & pvPutStructure, BitSet::shared_pointer const & /*putBitSet*/) @@ -1613,100 +654,49 @@ void CAChannelPut::put(PVStructure::shared_pointer const & pvPutStructure, } ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); if(!putRequester) return; - doPut putFunc = doPutFuncTable[channel->getNativeType()]; - if (putFunc) - { - // TODO now we always put all - if(block) { - channel->attachContext(); - int result = putFunc(channel, this, pvPutStructure); - if (result != ECA_NORMAL) - { - string message(ca_message(result)); - Status errorStatus(Status::STATUSTYPE_ERROR, message); - EXCEPTION_GUARD(putRequester->putDone(errorStatus, shared_from_this())); - } - } else { - channel->attachContext(); - int result = putFunc(channel,NULL, pvPutStructure); - if (result == ECA_NORMAL) - { - EXCEPTION_GUARD(putRequester->putDone(Status::Ok, shared_from_this())); - } - else - { - string message(ca_message(result)); - Status errorStatus(Status::STATUSTYPE_ERROR,message); - EXCEPTION_GUARD(putRequester->putDone(errorStatus, shared_from_this())); - } - } - } - else - { - // TODO remove - std::cout << "no put func implemented" << std::endl; - } - + Status status = dbdToPv->putToDBD(channel,pvPutStructure,block); + EXCEPTION_GUARD(putRequester->putDone(status, shared_from_this())); } void CAChannelPut::getDone(struct event_handler_args &args) { - if(DEBUG_LEVEL>1) { + if(DEBUG_LEVEL>1) { cout << "CAChannelPut::getDone " << channel->getChannelName() << endl; } + ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); if(!putRequester) return; - if (args.status == ECA_NORMAL) - { - copyDBRtoPVStructure copyFunc = copyFuncTable[getType]; - if (copyFunc) - copyFunc(args.dbr, args.count, pvStructure); - else - { - // TODO remove - std::cout << "no copy func implemented" << std::endl; - } - - EXCEPTION_GUARD(putRequester->getDone(Status::Ok, shared_from_this(), pvStructure, bitSet)); - } - else - { - Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(args.status))); - EXCEPTION_GUARD(putRequester->getDone(errorStatus, shared_from_this(), - PVStructure::shared_pointer(), BitSet::shared_pointer())); - } - + Status status = dbdToPv->getFromDBD(pvStructure,bitSet,args); + EXCEPTION_GUARD(putRequester->getDone(status, shared_from_this(), pvStructure, bitSet)); } void CAChannelPut::get() { if(DEBUG_LEVEL>1) { - cout << "CAChannelPut::get " << channel->getChannelName() << endl; + std::cout << "CAChannelPut::get " << channel->getChannelName() << endl; } ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock()); if(!putRequester) return; channel->attachContext(); - - int result = ca_array_get_callback(getType, channel->getElementCount(), + bitSet->clear(); + int result = ca_array_get_callback(dbdToPv->getRequestType(), + 0, channel->getChannelID(), ca_put_get_handler, this); - if (result == ECA_NORMAL) { result = ca_flush_io(); } - if (result == ECA_NORMAL) return; - string message(ca_message(result)); - Status errorStatus(Status::STATUSTYPE_ERROR, message); - EXCEPTION_GUARD(putRequester->getDone(errorStatus, shared_from_this(), - PVStructure::shared_pointer(), BitSet::shared_pointer())); + if (result != ECA_NORMAL) + { + string mess("CAChannelPut::get "); + mess += channel->getChannelName() + " message " +ca_message(result); + throw std::runtime_error(mess); + } } - -/* --------------- epics::pvData::ChannelRequest --------------- */ - Channel::shared_pointer CAChannelPut::getChannel() { return channel; @@ -1790,20 +780,37 @@ public: { Lock guard(mutex); if(monitorElementQueue.empty()) { - throw std::runtime_error("client error calling release"); + string mess("CAChannelMonitor::release client error calling release "); + throw std::runtime_error(mess); } monitorElementQueue.pop(); } }; +size_t CAChannelMonitor::num_instances; + CAChannelMonitorPtr CAChannelMonitor::create( CAChannel::shared_pointer const & channel, MonitorRequester::shared_pointer const & monitorRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { + if(DEBUG_LEVEL>0) { + cout << "CAChannelMonitor::create " << channel->getChannelName() << endl; + } return CAChannelMonitorPtr(new CAChannelMonitor(channel, monitorRequester, pvRequest)); } +CAChannelMonitor::CAChannelMonitor( + CAChannel::shared_pointer const & channel, + MonitorRequester::shared_pointer const & monitorRequester, + PVStructurePtr const & pvRequest) +: + channel(channel), + monitorRequester(monitorRequester), + pvRequest(pvRequest), + isStarted(false) +{} + CAChannelMonitor::~CAChannelMonitor() { if(DEBUG_LEVEL>0) { @@ -1818,39 +825,19 @@ CAChannelMonitor::~CAChannelMonitor() cerr << mess << endl; } -size_t CAChannelMonitor::num_instances; - -CAChannelMonitor::CAChannelMonitor( - CAChannel::shared_pointer const & channel, - MonitorRequester::shared_pointer const & monitorRequester, - PVStructurePtr const & pvRequest) -: - channel(channel), - monitorRequester(monitorRequester), - pvRequest(pvRequest), - isStarted(false), - firstTime(true) -{ - if(DEBUG_LEVEL>0) { - cout << "CAChannelMonitor::CAChannelMonitor() " << channel->getChannelName() << endl; - } -} +void CAChannelMonitor::channelCreated(const Status& status,Channel::shared_pointer const & c) +{} void CAChannelMonitor::activate() { + MonitorRequester::shared_pointer requester(monitorRequester.lock()); + if(!requester) return; if(DEBUG_LEVEL>0) { std::cout << "CAChannelMonitor::activate " << channel->getChannelName() << endl; } - MonitorRequester::shared_pointer requester(monitorRequester.lock()); - if(!requester) return; - if(pvStructure) throw std::runtime_error("CAChannelMonitor::activate() was called twice"); - getType = getDBRType(pvRequest, channel->getNativeType()); - pvStructure = createPVStructure(channel, getType, pvRequest); + dbdToPv = DbdToPv::create(channel,pvRequest,monitorIO); + pvStructure = dbdToPv->createPVStructure(); activeElement = MonitorElementPtr(new MonitorElement(pvStructure)); - pvCopy = PVCopy::create( - createPVStructure(channel, getType, pvRequest), - CreateRequest::create()->createRequest("field()"), - ""); int32 queueSize = 2; PVStructurePtr pvOptions = pvRequest->getSubField("record._options"); if (pvOptions) { @@ -1865,59 +852,18 @@ void CAChannelMonitor::activate() } monitorQueue = CACMonitorQueuePtr(new CACMonitorQueue(queueSize)); channel->addChannelMonitor(shared_from_this()); - if(channel->getConnectionState()==Channel::CONNECTED) { - EXCEPTION_GUARD(requester->monitorConnect(Status::Ok, shared_from_this(), - pvStructure->getStructure())); - } -} - -void CAChannelMonitor::channelCreated(const Status& status,Channel::shared_pointer const & c) -{ - if(DEBUG_LEVEL>0) { - std::cout << "CAChannelMonitor::channelCreated " << channel->getChannelName() << endl; - } - firstTime = true; - MonitorRequester::shared_pointer requester(monitorRequester.lock()); - if(!requester) return; - chtype newType = getDBRType(pvRequest, channel->getNativeType()); - if(newType!=getType) { - getType = getDBRType(pvRequest, channel->getNativeType()); - pvStructure = createPVStructure(channel, getType, pvRequest); - activeElement = MonitorElementPtr(new MonitorElement(pvStructure)); - pvCopy = PVCopy::create( - createPVStructure(channel, getType, pvRequest), - CreateRequest::create()->createRequest("field()"), - ""); - int32 queueSize = 2; - PVStructurePtr pvOptions = pvRequest->getSubField("record._options"); - if (pvOptions) { - PVStringPtr pvString = pvOptions->getSubField("queueSize"); - if (pvString) { - int size; - std::stringstream ss; - ss << pvString->get(); - ss >> size; - if (size > 1) queueSize = size; - } - } - monitorQueue = CACMonitorQueuePtr(new CACMonitorQueue(queueSize)); - } EXCEPTION_GUARD(requester->monitorConnect(Status::Ok, shared_from_this(), pvStructure->getStructure())); } + void CAChannelMonitor::channelStateChange( Channel::shared_pointer const & channel, Channel::ConnectionState connectionState) { - if(DEBUG_LEVEL>0) { - std::cout << "CAChannelMonitor::channelStateChange " << channel->getChannelName() << endl; - } - MonitorRequester::shared_pointer requester(monitorRequester.lock()); - if(!requester) return; - if(connectionState==Channel::DISCONNECTED || connectionState==Channel::DESTROYED) { - EXCEPTION_GUARD(requester->channelDisconnect(connectionState==Channel::DESTROYED);) - } + string mess("CAChannelMonitor::channelStateChange was called "); + mess += channel->getChannelName(); + throw std::runtime_error(mess); } @@ -1929,47 +875,35 @@ void CAChannelMonitor::channelDisconnect(bool destroy) MonitorRequester::shared_pointer requester(monitorRequester.lock()); if(!requester) return; EXCEPTION_GUARD(requester->channelDisconnect(destroy);) + if(!destroy) channel->addChannelMonitor(shared_from_this()); } void CAChannelMonitor::subscriptionEvent(struct event_handler_args &args) { if(DEBUG_LEVEL>1) { std::cout << "CAChannelMonitor::subscriptionEvent " - << channel->getChannelName() - << " firstTime " << (firstTime ? "true" : "false") - << endl; + << channel->getChannelName() << endl; } MonitorRequester::shared_pointer requester(monitorRequester.lock()); if(!requester) return; - if (args.status == ECA_NORMAL) + Status status = dbdToPv->getFromDBD(pvStructure,activeElement->changedBitSet,args); + + if(status.isOK()) { - copyDBRtoPVStructure copyFunc = copyFuncTable[getType]; - if (copyFunc) { - copyFunc(args.dbr, args.count, pvStructure); - pvCopy->updateMasterSetBitSet(pvStructure,activeElement->changedBitSet); - if(firstTime) { - activeElement->changedBitSet->clear(); - activeElement->overrunBitSet->clear(); - activeElement->changedBitSet->set(0); - firstTime = false; - } - if(monitorQueue->event(pvStructure,activeElement)) { - activeElement->changedBitSet->clear(); - activeElement->overrunBitSet->clear(); - } else { - *(activeElement->overrunBitSet) |= *(activeElement->changedBitSet); - } - - // call monitorRequester even if queue is full - requester->monitorEvent(shared_from_this()); + if(monitorQueue->event(pvStructure,activeElement)) { + activeElement->changedBitSet->clear(); + activeElement->overrunBitSet->clear(); } else { - std::cout << "no copy func implemented" << std::endl; - + *(activeElement->overrunBitSet) |= *(activeElement->changedBitSet); } + + // call monitorRequester even if queue is full + requester->monitorEvent(shared_from_this()); } else { string mess("CAChannelMonitor::subscriptionEvent "); + mess += channel->getChannelName(); mess += ca_message(args.status); throw std::runtime_error(mess); } @@ -1986,21 +920,8 @@ epics::pvData::Status CAChannelMonitor::start() return status; } channel->attachContext(); - - /* - From R3.14.12 onwards when using the IOC server and the C++ client libraries monitor callbacks - replies will give a CA client application the current number of elements in an array field, - provided they specified an element count of zero in their original request. - The element count is passed in the callback argument structure. - Prior to R3.14.12 you could request a zero-length subscription and the zero would mean - “use the value of chid->element_count() for this particular channel”, - but the length of the data you got in your callbacks would never change - (the server would zero-fill everything after the current length of the field). - */ - - // TODO DBE_PROPERTY support monitorQueue->start(); - int result = ca_create_subscription(getType, + int result = ca_create_subscription(dbdToPv->getRequestType(), 0, channel->getChannelID(), DBE_VALUE, ca_subscription_handler, this, diff --git a/src/ca/caChannel.h b/src/ca/caChannel.h index ad3986e..6d49186 100644 --- a/src/ca/caChannel.h +++ b/src/ca/caChannel.h @@ -11,13 +11,12 @@ #include #include -#include - /* for CA */ #include #include "caProviderPvt.h" +#include "dbdToPv.h" namespace epics { namespace pvAccess { @@ -71,11 +70,6 @@ public: void disconnected(); chid getChannelID(); - chtype getNativeType(); - unsigned getElementCount(); - epics::pvData::Structure::const_shared_pointer getStructure(); - - /* --------------- epics::pvAccess::Channel --------------- */ virtual std::tr1::shared_ptr getProvider(); virtual std::string getRemoteAddress(); @@ -89,15 +83,15 @@ public: virtual ChannelGet::shared_pointer createChannelGet( ChannelGetRequester::shared_pointer const & channelGetRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); virtual ChannelPut::shared_pointer createChannelPut( ChannelPutRequester::shared_pointer const & channelPutRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); virtual Monitor::shared_pointer createMonitor( MonitorRequester::shared_pointer const & monitorRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); virtual void printInfo(std::ostream& out); @@ -128,10 +122,7 @@ private: ChannelRequester::weak_pointer channelRequester; chid channelID; - chtype channelType; - unsigned elementCount; bool channelCreated; - epics::pvData::Structure::const_shared_pointer structure; epics::pvData::Mutex requestsMutex; @@ -159,7 +150,7 @@ public: static CAChannelGet::shared_pointer create(CAChannel::shared_pointer const & channel, ChannelGetRequester::shared_pointer const & channelGetRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); virtual ~CAChannelGet(); @@ -179,7 +170,7 @@ public: Channel::shared_pointer const & channel); virtual void channelStateChange( Channel::shared_pointer const & channel, - Channel::ConnectionState connectionState); + Channel::ConnectionState cosnectionState); virtual std::string getRequesterName() { return "CAChannelGet";} /* --------------- ChannelBaseRequester --------------- */ virtual void channelDisconnect(bool destroy); @@ -192,15 +183,13 @@ private: CAChannelGet(CAChannel::shared_pointer const & _channel, ChannelGetRequester::shared_pointer const & _channelGetRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); CAChannelPtr channel; ChannelGetRequester::weak_pointer channelGetRequester; - const epics::pvData::PVStructure::shared_pointer pvRequest; - bool firstTime; + epics::pvData::PVStructurePtr const & pvRequest; - chtype getType; - epics::pvData::PVCopyPtr pvCopy; + DbdToPvPtr dbdToPv; epics::pvData::PVStructure::shared_pointer pvStructure; epics::pvData::BitSet::shared_pointer bitSet; }; @@ -221,11 +210,10 @@ public: static CAChannelPut::shared_pointer create(CAChannel::shared_pointer const & channel, ChannelPutRequester::shared_pointer const & channelPutRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); virtual ~CAChannelPut(); - void putDone(struct event_handler_args &args); void getDone(struct event_handler_args &args); /* --------------- epics::pvAccess::ChannelPut --------------- */ @@ -253,7 +241,7 @@ public: /* --------------- ChannelBaseRequester --------------- */ virtual void channelDisconnect(bool destroy); - void activate(); + void activate(); private: /* --------------- Destroyable --------------- */ @@ -262,14 +250,14 @@ private: CAChannelPut(CAChannel::shared_pointer const & _channel, ChannelPutRequester::shared_pointer const & _channelPutRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); CAChannelPtr channel; ChannelPutRequester::weak_pointer channelPutRequester; const epics::pvData::PVStructure::shared_pointer pvRequest; bool block; - chtype getType; + DbdToPvPtr dbdToPv; epics::pvData::PVStructure::shared_pointer pvStructure; epics::pvData::BitSet::shared_pointer bitSet; }; @@ -291,7 +279,7 @@ public: static CAChannelMonitor::shared_pointer create(CAChannel::shared_pointer const & channel, MonitorRequester::shared_pointer const & monitorRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); virtual ~CAChannelMonitor(); @@ -323,17 +311,15 @@ private: CAChannelMonitor(CAChannel::shared_pointer const & _channel, MonitorRequester::shared_pointer const & _monitorRequester, - epics::pvData::PVStructure::shared_pointer const & pvRequest); + epics::pvData::PVStructurePtr const & pvRequest); CAChannelPtr channel; MonitorRequester::weak_pointer monitorRequester; const epics::pvData::PVStructure::shared_pointer pvRequest; bool isStarted; - chtype getType; - bool firstTime; - epics::pvData::PVCopyPtr pvCopy; + DbdToPvPtr dbdToPv; epics::pvData::PVStructure::shared_pointer pvStructure; epics::pvData::MonitorElementPtr activeElement; evid eventID; diff --git a/src/ca/caProvider.cpp b/src/ca/caProvider.cpp index 6ec6fb9..c434283 100644 --- a/src/ca/caProvider.cpp +++ b/src/ca/caProvider.cpp @@ -66,6 +66,7 @@ CAChannelProvider::~CAChannelProvider() } caChannelList.clear(); } + attachContext(); while(!channelQ.empty()) { if(DEBUG_LEVEL>0) { std::cout << "disconnectAllChannels calling disconnectChannel " @@ -75,7 +76,6 @@ CAChannelProvider::~CAChannelProvider() channelQ.front()->disconnectChannel(); channelQ.pop(); } - attachContext(); ca_flush_io(); ca_context_destroy(); } diff --git a/src/ca/caStatus.cpp b/src/ca/caStatus.cpp deleted file mode 100644 index 3e9d352..0000000 --- a/src/ca/caStatus.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright - See the COPYRIGHT that is included with this distribution. - * pvAccessCPP is distributed subject to a Software License Agreement found - * in file LICENSE that is included with this distribution. - */ - -#define epicsExportSharedSymbols -#include - -namespace epics { -namespace pvAccess { -namespace ca { - -epicsShareDef std::string dbrStatus2alarmMessage[] = { - "NO_ALARM", // 0 .. - "READ_ALARM", - "WRITE_ALARM", - "HIHI_ALARM", - "HIGH_ALARM", - "LOLO_ALARM", - "LOW_ALARM", - "STATE_ALARM", - "COS_ALARM", - "COMM_ALARM", - "TIMEOUT_ALARM", - "HW_LIMIT_ALARM", - "CALC_ALARM", - "SCAN_ALARM", - "LINK_ALARM", - "SOFT_ALARM", - "BAD_SUB_ALARM", - "UDF_ALARM", - "DISABLE_ALARM", - "SIMM_ALARM", - "READ_ACCESS_ALARM", - "WRITE_ACCESS_ALARM" // .. 21 -}; - -epicsShareDef int dbrStatus2alarmStatus[] = { - noStatus, //"NO_ALARM" - driverStatus, //"READ_ALARM", - driverStatus, //"WRITE_ALARM", - recordStatus, //"HIHI_ALARM", - recordStatus, //"HIGH_ALARM", - recordStatus, //"LOLO_ALARM", - recordStatus, //"LOW_ALARM", - recordStatus, //"STATE_ALARM", - recordStatus, //"COS_ALARM", - driverStatus, //"COMM_ALARM", - driverStatus, //"TIMEOUT_ALARM", - deviceStatus, //"HW_LIMIT_ALARM", - recordStatus, //"CALC_ALARM", - dbStatus, //"SCAN_ALARM", - dbStatus, //"LINK_ALARM", - dbStatus, //"SOFT_ALARM", - confStatus, //"BAD_SUB_ALARM", - recordStatus, //"UDF_ALARM", - recordStatus, //"DISABLE_ALARM", - recordStatus, //"SIMM_ALARM", - clientStatus, //"READ_ACCESS_ALARM", - clientStatus //"WRITE_ACCESS_ALARM" // .. 21 -}; - - -} -} -} - - diff --git a/src/ca/dbdToPv.cpp b/src/ca/dbdToPv.cpp new file mode 100644 index 0000000..b8313cf --- /dev/null +++ b/src/ca/dbdToPv.cpp @@ -0,0 +1,926 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * pvAccessCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "caChannel.h" +#define epicsExportSharedSymbols +#include "dbdToPv.h" + +using namespace epics::pvData; +using std::string; +using std::ostringstream; +using std::cout; +using std::cerr; +using std::endl; + +namespace epics { +namespace pvAccess { +namespace ca { + +#define CA_TIMEOUT 2.0 +#define CA_PRIORITY 50 + +static void enumChoicesHandler(struct event_handler_args args) +{ + DbdToPv *dbdToPv = static_cast(args.usr); + dbdToPv->getChoicesDone(args); +} + +static void description_connection_handler(struct connection_handler_args args) +{ + DbdToPv *dbdToPv = static_cast(ca_puser(args.chid)); + dbdToPv->descriptionConnected(args); +} + +static void descriptionHandler(struct event_handler_args args) +{ + DbdToPv *dbdToPv = static_cast(args.usr); + dbdToPv->getDescriptionDone(args); +} + +static void putHandler(struct event_handler_args args) +{ + DbdToPv *dbdToPv = static_cast(args.usr); + dbdToPv->putDone(args); +} + +DbdToPvPtr DbdToPv::create( + CAChannelPtr const & caChannel, + PVStructurePtr const & pvRequest, + IOType ioType + ) +{ + DbdToPvPtr dbdToPv(new DbdToPv(ioType)); + dbdToPv->activate(caChannel,pvRequest); + return dbdToPv; +} + +DbdToPv::DbdToPv(IOType ioType) +: ioType(ioType), + fieldRequested(false), + alarmRequested(false), + timeStampRequested(false), + displayRequested(false), + controlRequested(false), + valueAlarmRequested(false), + isArray(false), + firstTime(true), + caValueType(-1), + caRequestType(-1) +{ +} + +static ScalarType dbr2ST[] = +{ + pvString, // DBR_STRING = 0 + pvShort, // DBR_SHORT. DBR_INT = 1 + pvFloat, // DBR_FLOAT = 2 + static_cast(-1), // DBR_ENUM = 3 + pvByte, // DBR_CHAR = 4 + pvInt, // DBR_LONG = 5 + pvDouble // DBR_DOUBLE = 6 +}; + +static chtype getDbrType(const ScalarType scalarType) +{ + switch(scalarType) + { + case pvString : return DBR_STRING; + case pvByte : return DBR_CHAR; + case pvShort : return DBR_SHORT; + case pvInt : return DBR_LONG; + case pvFloat : return DBR_FLOAT; + case pvDouble : return DBR_DOUBLE; + default: break; + } + throw std::runtime_error("getDbr: illegal scalarType"); +} + + +void DbdToPv::activate( + CAChannelPtr const & caChannel, + PVStructurePtr const & pvRequest) +{ + chid channelID = caChannel->getChannelID(); + chtype channelType = ca_field_type(channelID); + caValueType = (channelType==DBR_ENUM ? DBR_ENUM : getDbrType(dbr2ST[channelType])); + PVStructurePtr fieldPVStructure = pvRequest->getSubField("field"); + if(fieldPVStructure->getPVFields().size()==0) + { + fieldRequested = true; + alarmRequested = true; + timeStampRequested = true; + displayRequested = true; + controlRequested = true; + valueAlarmRequested = true; + } else { + if(fieldPVStructure->getSubField("value")) fieldRequested = true; + if(fieldPVStructure->getSubField("alarm")) alarmRequested = true; + if(fieldPVStructure->getSubField("timeStamp")) timeStampRequested = true; + if(fieldPVStructure->getSubField("display")) displayRequested = true; + if(fieldPVStructure->getSubField("control")) controlRequested = true; + if(fieldPVStructure->getSubField("valueAlarm")) valueAlarmRequested = true; + } + switch(ioType) + { + case getIO : break; + case putIO: + alarmRequested = false; + timeStampRequested = false; // no break + case monitorIO: + displayRequested = false; + controlRequested = false; + valueAlarmRequested = false; + } + StandardFieldPtr standardField = getStandardField(); + if(channelType==DBR_ENUM) + { + 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; + } + structure = standardField->enumerated(properties); + int result = ca_array_get_callback(DBR_GR_ENUM, + 1, + channelID, enumChoicesHandler, this); + if (result == ECA_NORMAL) result = ca_flush_io(); + if (result != ECA_NORMAL) { + string mess(caChannel->getChannelName()); + mess += " DbdToPv::activate getting enum cnoices "; + mess += ca_message(result); + throw std::runtime_error(mess); + } + // NOTE: we do not wait here, since all subsequent request (over TCP) is serialized + // and will guarantee that enumChoicesHandler is called first + return; + } + if(ca_element_count(channelID)!=1) isArray = true; + if(isArray) + { + controlRequested = false; + valueAlarmRequested = false; + } + ScalarType st = dbr2ST[channelType]; + if(st==pvString) { + displayRequested = false; + controlRequested = false; + valueAlarmRequested = false; + } + if(controlRequested || displayRequested || valueAlarmRequested) timeStampRequested = false; + + FieldCreatePtr fieldCreate(FieldCreate::getFieldCreate()); + PVDataCreatePtr pvDataCreate(PVDataCreate::getPVDataCreate()); + FieldBuilderPtr fieldBuilder(fieldCreate->createFieldBuilder()); + if(fieldRequested) { + if(isArray) { + fieldBuilder->addArray("value",st); + } else { + fieldBuilder->add("value",st); + } + } + if(alarmRequested) fieldBuilder->add("alarm",standardField->alarm()); + if(timeStampRequested) fieldBuilder->add("timeStamp",standardField->timeStamp()); + if(displayRequested) fieldBuilder->add("display",standardField->display()); + if(controlRequested) fieldBuilder->add("control",standardField->control()); + if(valueAlarmRequested) { + switch(st) + { + case pvByte: + fieldBuilder->add("valueAlarm",standardField->byteAlarm()); break; + case pvShort: + fieldBuilder->add("valueAlarm",standardField->shortAlarm()); break; + case pvInt: + fieldBuilder->add("valueAlarm",standardField->intAlarm()); break; + case pvFloat: + fieldBuilder->add("valueAlarm",standardField->floatAlarm()); break; + case pvDouble: + fieldBuilder->add("valueAlarm",standardField->doubleAlarm()); break; + default: + throw std::runtime_error("DbDToPv::activate: bad type"); + } + } + structure = fieldBuilder->createStructure(); + 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; + } + if(displayRequested) { + chid channelID; + string name(caChannel->getChannelName() + ".DESC"); + int result = ca_create_channel(name.c_str(), + description_connection_handler, + this, + CA_PRIORITY, // TODO mapping + &channelID); + if (result == ECA_NORMAL) result = ca_flush_io(); + if (result != ECA_NORMAL) { + string mess(caChannel->getChannelName()); + mess += " DbdToPv::activate getting description "; + mess += ca_message(result); + throw std::runtime_error(mess); + } + } +} + +void DbdToPv::descriptionConnected(struct connection_handler_args args) +{ +cout << "DbdToPv::descriptionConnected\n"; + if (args.op != CA_OP_CONN_UP) return; + ca_array_get_callback(DBR_STRING, + 0, + args.chid, descriptionHandler, this); +} + +void DbdToPv::getDescriptionDone(struct event_handler_args &args) +{ +cout << "DbdToPv::getDescriptionDone\n"; + if(args.status!=ECA_NORMAL) return; + const dbr_string_t *value = static_cast(dbr_value_ptr(args.dbr,DBR_STRING)); + description = string(*value); + ca_clear_channel(args.chid); +} + +void DbdToPv::getChoicesDone(struct event_handler_args &args) +{ + if(args.status!=ECA_NORMAL) + { + string message("DbdToPv::getChoicesDone ca_message "); + message += ca_message(args.status); + throw std::runtime_error(message); + } + const dbr_gr_enum* dbr_enum_p = static_cast(args.dbr); + size_t num = dbr_enum_p->no_str; + choices.reserve(num); + for(size_t i=0; istrs[i][0])); +} + +chtype DbdToPv::getRequestType() +{ + if(caRequestType<0) { + throw std::runtime_error("DbDToPv::getRequestType: bad type"); + } + return caRequestType; +} + +PVStructurePtr DbdToPv::createPVStructure() +{ + return getPVDataCreate()->createPVStructure(structure); +} + +Status DbdToPv::getFromDBD( + PVStructurePtr const & pvStructure, + BitSet::shared_pointer const & bitSet, + struct event_handler_args &args) +{ + if(args.status!=ECA_NORMAL) + { + Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(args.status))); + return errorStatus; + } + if(fieldRequested) + { + void * value = dbr_value_ptr(args.dbr,caRequestType); + long count = args.count; + switch(caValueType) { + case DBR_ENUM: + { + const dbr_enum_t *dbrval = static_cast(value); + PVIntPtr value = pvStructure->getSubField("value.index"); + value->put(*dbrval); + PVStringArrayPtr pvChoices + = pvStructure->getSubField("value.choices"); + if(pvChoices->getLength()==0) + { + ConvertPtr convert = getConvert(); + size_t n = choices.size(); + pvChoices->setLength(n); + convert->fromStringArray(pvChoices,0,n,choices,0); + bitSet->set(pvStructure->getSubField("value")->getFieldOffset()); + } else { + bitSet->set(value->getFieldOffset()); + } + 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; + } + default: + Status errorStatus( + Status::STATUSTYPE_ERROR, string("DbdToPv::FromDBD 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; + double lower_disp_limit; + double upper_alarm_limit; + double upper_warning_limit; + double lower_warning_limit; + double lower_alarm_limit; + double upper_ctrl_limit; + double lower_ctrl_limit; + 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()); + } + } + if(timeStampRequested) { + PVStructurePtr pvTimeStamp(pvStructure->getSubField("timeStamp")); + if(caTimeStamp.secPastEpoch!=stamp.secPastEpoch) { + caTimeStamp.secPastEpoch = stamp.secPastEpoch; + PVLongPtr pvSeconds(pvTimeStamp->getSubField("secondsPastEpoch")); + pvSeconds->put(stamp.secPastEpoch+posixEpochAtEpicsEpoch); + bitSet->set(pvSeconds->getFieldOffset()); + } + if(caTimeStamp.nsec!=stamp.nsec) { + caTimeStamp.secPastEpoch = stamp.secPastEpoch; + PVIntPtr pvNano(pvTimeStamp->getSubField("nanoseconds")); + pvNano->put(stamp.nsec); + bitSet->set(pvNano->getFieldOffset()); + } + + } + if(firstTime) { + firstTime = false; + bitSet->clear(); + bitSet->set(0); + } + return Status::Ok; +} + +Status DbdToPv::putToDBD( + CAChannelPtr const & caChannel, + PVStructurePtr const & pvStructure, + bool block) +{ + chid channelID = caChannel->getChannelID(); + const void *pValue = NULL; + unsigned long count = 1; + dbr_enum_t indexvalue(0); + dbr_char_t bvalue(0); + dbr_short_t svalue(0); + dbr_long_t ivalue(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) { + PVStringArrayPtr pvValue = pvStructure->getSubField("value"); + count = pvValue->getLength(); + if(count<1) break; + int nbytes = count*MAX_STRING_SIZE; + ca_stringBuffer = new char[nbytes]; + memset(ca_stringBuffer, 0, nbytes); + pValue = ca_stringBuffer; + PVStringArray::const_svector stringArray(pvValue->view()); + char *pnext = ca_stringBuffer; + for(size_t i=0; i= MAX_STRING_SIZE) len = MAX_STRING_SIZE - 1; + memcpy(pnext, value.c_str(), len); + pnext += MAX_STRING_SIZE; + } + } else { + pValue = pvStructure->getSubField("value")->get().c_str(); + } + 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) { + caChannel->attachContext(); + result = ca_array_put_callback(caValueType,count,channelID,pValue,putHandler,this); + if(result==ECA_NORMAL) { + ca_flush_io(); + if(!waitForCallback.wait(2.0)) { + throw std::runtime_error("DbDToPv::putToDBD waitForCallback timeout"); + } + return putStatus; + } + } 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; +} + +void DbdToPv::putDone(struct event_handler_args &args) +{ + if(args.status!=ECA_NORMAL) + { + string message("DbdToPv::putDone ca_message "); + message += ca_message(args.status); + putStatus = Status(Status::STATUSTYPE_ERROR, string(ca_message(args.status))); + } else { + putStatus = Status::Ok; + } + waitForCallback.signal(); +} + + +}}} diff --git a/src/ca/dbdToPv.h b/src/ca/dbdToPv.h new file mode 100644 index 0000000..72d63e3 --- /dev/null +++ b/src/ca/dbdToPv.h @@ -0,0 +1,138 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * pvAccessCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/** + * @author mrk + * @date 2018.03 + */ +#ifndef DbdToPv_H +#define DbdToPv_H + +#include +#include +#include +#include +#include "caChannel.h" + +namespace epics { +namespace pvAccess { +namespace ca { + +enum IOType {getIO,putIO,monitorIO}; + +class AlarmDbd; +typedef std::tr1::shared_ptr AlarmDbdPtr; +class TimeStampDbd; +typedef std::tr1::shared_ptr TimeStampDbdPtr; +class DisplayDbd; +typedef std::tr1::shared_ptr DisplayDbdPtr; +class ControlDbd; +typedef std::tr1::shared_ptr ControlDbdPtr; +class ValueAlarmDbd; +typedef std::tr1::shared_ptr ValueAlarmDbdPtr; + +struct CaAlarm +{ + dbr_short_t status; + dbr_short_t severity; +}; + +struct CaDisplay +{ + double lower_disp_limit; + double upper_disp_limit; + std::string units; + std::string format; +}; + +struct CaControl +{ + double upper_ctrl_limit; + double lower_ctrl_limit; +}; + +struct CaValueAlarm +{ + double upper_alarm_limit; + double upper_warning_limit; + double lower_warning_limit; + double lower_alarm_limit; +}; + +class DbdToPv; +typedef std::tr1::shared_ptr DbdToPvPtr; + +/** + * @brief DbdToPv converts between DBD data and pvData. + * + * + */ +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( + epics::pvData::PVStructurePtr const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet, + struct event_handler_args &args + ); + epics::pvData::Status putToDBD( + CAChannelPtr const & caChannel, + epics::pvData::PVStructurePtr const & pvStructure, + bool block + ); + void getChoicesDone(struct event_handler_args &args); + 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 + ); + IOType ioType; + bool fieldRequested; + bool alarmRequested; + bool timeStampRequested; + bool displayRequested; + bool controlRequested; + bool valueAlarmRequested; + bool isArray; + bool firstTime; + chtype caValueType; + chtype caRequestType; + epicsTimeStamp caTimeStamp; + CaAlarm caAlarm; + CaDisplay caDisplay; + CaControl caControl; + CaValueAlarm caValueAlarm; + std::string description; + epics::pvData::Event waitForCallback; + epics::pvData::Status putStatus; + epics::pvData::Structure::const_shared_pointer structure; + std::vector choices; +}; + +} +} +} + +#endif /* DbdToPv_H */ diff --git a/src/ca/pv/caStatus.h b/src/ca/pv/caStatus.h deleted file mode 100644 index 33ba6f3..0000000 --- a/src/ca/pv/caStatus.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright - See the COPYRIGHT that is included with this distribution. - * pvAccessCPP is distributed subject to a Software License Agreement found - * in file LICENSE that is included with this distribution. - */ - -#ifndef CASTATUS_H -#define CASTATUS_H - -#include -#include - -namespace epics { -namespace pvAccess { -namespace ca { - -enum AlarmStatus { - noStatus,deviceStatus,driverStatus,recordStatus, - dbStatus,confStatus,undefinedStatus,clientStatus -}; - -epicsShareExtern std::string dbrStatus2alarmMessage[]; -epicsShareExtern int dbrStatus2alarmStatus[]; - -} -} -} - -#endif /* CASTATUS_H */