From e9d2114e965788e6653f3cf5b19cba1a728bc5d3 Mon Sep 17 00:00:00 2001 From: mrkraimer Date: Mon, 24 Sep 2018 13:45:21 -0400 Subject: [PATCH] latest changes to match caProvider.html --- src/ca/caChannel.cpp | 6 +- src/ca/dbdToPv.cpp | 179 ++++++++++++++++++++----------------------- src/ca/dbdToPv.h | 10 +-- 3 files changed, 88 insertions(+), 107 deletions(-) diff --git a/src/ca/caChannel.cpp b/src/ca/caChannel.cpp index bd5eecb..d3baef2 100644 --- a/src/ca/caChannel.cpp +++ b/src/ca/caChannel.cpp @@ -402,8 +402,7 @@ void CAChannelGetField::callRequester(CAChannelPtr const & caChannel) if(!requester) return; PVStructurePtr pvRequest(createRequest("")); DbdToPvPtr dbdToPv = DbdToPv::create(caChannel,pvRequest,getIO); - PVStructurePtr pvStructure = dbdToPv->createPVStructure(); - Structure::const_shared_pointer structure(pvStructure->getStructure()); + Structure::const_shared_pointer structure(dbdToPv->getStructure()); Field::const_shared_pointer field = subField.empty() ? std::tr1::static_pointer_cast(structure) : @@ -471,6 +470,7 @@ void CAChannelGet::activate() std::cout << "CAChannelGet::activate " << channel->getChannelName() << endl; } dbdToPv = DbdToPv::create(channel,pvRequest,getIO); + dbdToPv->getChoices(channel); pvStructure = dbdToPv->createPVStructure(); bitSet = BitSetPtr(new BitSet(pvStructure->getStructure()->getNumberFields())); notifyGetRequester = NotifyGetRequesterPtr(new NotifyGetRequester()); @@ -595,6 +595,7 @@ void CAChannelPut::activate() cout << "CAChannelPut::activate " << channel->getChannelName() << endl; } dbdToPv = DbdToPv::create(channel,pvRequest,putIO); + dbdToPv->getChoices(channel); pvStructure = dbdToPv->createPVStructure(); bitSet = BitSetPtr(new BitSet(pvStructure->getStructure()->getNumberFields())); PVStringPtr pvString = pvRequest->getSubField("record._options.block"); @@ -854,6 +855,7 @@ void CAChannelMonitor::activate() std::cout << "CAChannelMonitor::activate " << channel->getChannelName() << endl; } dbdToPv = DbdToPv::create(channel,pvRequest,monitorIO); + dbdToPv->getChoices(channel); pvStructure = dbdToPv->createPVStructure(); activeElement = MonitorElementPtr(new MonitorElement(pvStructure)); int32 queueSize = 2; diff --git a/src/ca/dbdToPv.cpp b/src/ca/dbdToPv.cpp index 09f30f7..409a0ec 100644 --- a/src/ca/dbdToPv.cpp +++ b/src/ca/dbdToPv.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -23,6 +24,7 @@ using namespace epics::pvData; using std::string; using std::ostringstream; +using std::cout; namespace epics { namespace pvAccess { @@ -30,23 +32,7 @@ namespace ca { #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); -} DbdToPvPtr DbdToPv::create( CAChannelPtr const & caChannel, @@ -60,7 +46,7 @@ DbdToPvPtr DbdToPv::create( DbdToPv::DbdToPv(IOType ioType) : ioType(ioType), - fieldRequested(false), + valueRequested(false), alarmRequested(false), timeStampRequested(false), displayRequested(false), @@ -68,8 +54,6 @@ DbdToPv::DbdToPv(IOType ioType) valueAlarmRequested(false), isArray(false), firstTime(true), - choicesValid(false), - waitForChoicesValid(false), caValueType(-1), caRequestType(-1), maxElements(0) @@ -104,6 +88,42 @@ static chtype getDbrType(const ScalarType scalarType) throw std::runtime_error("getDbr: illegal scalarType"); } +static dbr_short_t convertDBstatus(dbr_short_t dbStatus) +{ + switch(dbStatus) { + case NO_ALARM: + return noStatus; + case READ_ALARM: + case WRITE_ALARM: + case HIHI_ALARM: + case HIGH_ALARM: + case LOLO_ALARM: + case LOW_ALARM: + case STATE_ALARM: + case COS_ALARM: + case HW_LIMIT_ALARM: + return deviceStatus; + case COMM_ALARM: + case TIMEOUT_ALARM: + return driverStatus; + case CALC_ALARM: + case SCAN_ALARM: + case LINK_ALARM: + case SOFT_ALARM: + case BAD_SUB_ALARM: + return recordStatus; + case DISABLE_ALARM: + case SIMM_ALARM: + case READ_ACCESS_ALARM: + case WRITE_ACCESS_ALARM: + return dbStatus; + case UDF_ALARM: + return undefinedStatus; + default: + return undefinedStatus; // UNDEFINED + } + +} void DbdToPv::activate( CAChannelPtr const & caChannel, @@ -131,14 +151,14 @@ void DbdToPv::activate( } if(fieldPVStructure->getPVFields().size()==0) { - fieldRequested = true; + valueRequested = true; alarmRequested = true; timeStampRequested = true; displayRequested = true; controlRequested = true; valueAlarmRequested = true; } else { - if(fieldPVStructure->getSubField("value")) fieldRequested = true; + if(fieldPVStructure->getSubField("value")) valueRequested = true; if(fieldPVStructure->getSubField("alarm")) alarmRequested = true; if(fieldPVStructure->getSubField("timeStamp")) timeStampRequested = true; if(fieldPVStructure->getSubField("display")) displayRequested = true; @@ -173,18 +193,7 @@ void DbdToPv::activate( } caRequestType = (properties.size()==0 ? DBR_ENUM : DBR_TIME_ENUM); 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; } maxElements = ca_element_count(channelID); @@ -204,7 +213,7 @@ void DbdToPv::activate( FieldCreatePtr fieldCreate(FieldCreate::getFieldCreate()); PVDataCreatePtr pvDataCreate(PVDataCreate::getPVDataCreate()); FieldBuilderPtr fieldBuilder(fieldCreate->createFieldBuilder()); - if(fieldRequested) { + if(valueRequested) { if(isArray) { fieldBuilder->addArray("value",st); } else { @@ -242,38 +251,27 @@ void DbdToPv::activate( } else { caRequestType = dbf_type_to_DBR(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); - } + +} + +chtype DbdToPv::getRequestType() +{ + if(caRequestType<0) { + throw std::runtime_error("DbDToPv::getRequestType: bad type"); } + return caRequestType; } -void DbdToPv::descriptionConnected(struct connection_handler_args args) +Structure::const_shared_pointer DbdToPv::getStructure() { - if (args.op != CA_OP_CONN_UP) return; - ca_array_get_callback(DBR_STRING, - 0, - args.chid, descriptionHandler, this); + return structure; } -void DbdToPv::getDescriptionDone(struct event_handler_args &args) + +static void enumChoicesHandler(struct event_handler_args args) { - 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); + DbdToPv *dbdToPv = static_cast(args.usr); + dbdToPv->getChoicesDone(args); } void DbdToPv::getChoicesDone(struct event_handler_args &args) @@ -288,21 +286,29 @@ void DbdToPv::getChoicesDone(struct event_handler_args &args) size_t num = dbr_enum_p->no_str; choices.reserve(num); for(size_t i=0; istrs[i][0])); - bool signal = false; - { - Lock lock(choicesMutex); - choicesValid = true; - if(waitForChoicesValid) signal = true; - } - if(signal) choicesEvent.signal(); + choicesEvent.signal(); } -chtype DbdToPv::getRequestType() + +void DbdToPv::getChoices(CAChannelPtr const & caChannel) { - if(caRequestType<0) { - throw std::runtime_error("DbDToPv::getRequestType: bad type"); + if(caRequestType==DBR_ENUM||caRequestType==DBR_TIME_ENUM) + { + caChannel->attachContext(); + chid channelID = caChannel->getChannelID(); + int result = ca_array_get_callback(DBR_GR_ENUM, + 1, + channelID, enumChoicesHandler, this); + if (result == ECA_NORMAL) { + result = ca_flush_io(); + choicesEvent.wait(); + } else { + string mess(caChannel->getChannelName()); + mess += " DbdToPv::activate getting enum cnoices "; + mess += ca_message(result); + throw std::runtime_error(mess); + } } - return caRequestType; } PVStructurePtr DbdToPv::createPVStructure() @@ -368,7 +374,7 @@ Status DbdToPv::getFromDBD( Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(args.status))); return errorStatus; } - if(fieldRequested) + if(valueRequested) { void * value = dbr_value_ptr(args.dbr,caRequestType); if(isArray) { @@ -461,7 +467,7 @@ Status DbdToPv::getFromDBD( PVIntPtr pvStatus(pvAlarm->getSubField("status")); if(caAlarm.status!=status) { caAlarm.status = status; - pvStatus->put(status); + pvStatus->put(convertDBstatus(status)); string message("UNKNOWN STATUS"); if(status<=ALARM_NSTATUS) message = string(epicsAlarmConditionStrings[status]); pvMessage->put(message); @@ -488,7 +494,7 @@ Status DbdToPv::getFromDBD( bitSet->set(pvSeconds->getFieldOffset()); } if(caTimeStamp.nsec!=stamp.nsec) { - caTimeStamp.secPastEpoch = stamp.secPastEpoch; + caTimeStamp.nsec = stamp.nsec; PVIntPtr pvNano(pvTimeStamp->getSubField("nanoseconds")); pvNano->put(stamp.nsec); bitSet->set(pvNano->getFieldOffset()); @@ -590,14 +596,6 @@ Status DbdToPv::getFromDBD( 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; @@ -668,6 +666,8 @@ Status DbdToPv::getFromDBD( return Status::Ok; } + + template const void * put_DBRScalar(dbrT *val,PVScalar::shared_pointer const & pvScalar) { @@ -750,23 +750,6 @@ Status DbdToPv::putToDBD( switch(caValueType) { case DBR_ENUM: { - bool wait = false; - { - Lock lock(choicesMutex); - if(!choicesValid) { - wait = true; - waitForChoicesValid = true; - } - } - bool result = true; - if(wait) { - result = choicesEvent.wait(5.0); - } - if(!result) { - Status errorStatus( - Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD ")); - return errorStatus; - } dbr_enum_t indexvalue = pvStructure->getSubField("value.index")->get(); pValue = &indexvalue; break; diff --git a/src/ca/dbdToPv.h b/src/ca/dbdToPv.h index 5ee77b5..7fa77d6 100644 --- a/src/ca/dbdToPv.h +++ b/src/ca/dbdToPv.h @@ -89,6 +89,8 @@ public: epics::pvData::PVStructurePtr const & pvRequest, IOType ioType ); + epics::pvData::Structure::const_shared_pointer getStructure(); + void getChoices(CAChannelPtr const & caChannel); epics::pvData::PVStructurePtr createPVStructure(); chtype getRequestType(); epics::pvData::Status getFromDBD( @@ -104,8 +106,6 @@ public: void *userArg ); void getChoicesDone(struct event_handler_args &args); - void descriptionConnected(struct connection_handler_args args); - void getDescriptionDone(struct event_handler_args &args); private: DbdToPv(IOType ioType); void activate( @@ -113,7 +113,7 @@ private: epics::pvData::PVStructurePtr const & pvRequest ); IOType ioType; - bool fieldRequested; + bool valueRequested; bool alarmRequested; bool timeStampRequested; bool displayRequested; @@ -121,19 +121,15 @@ private: bool valueAlarmRequested; bool isArray; bool firstTime; - bool choicesValid; - bool waitForChoicesValid; chtype caValueType; chtype caRequestType; unsigned long maxElements; - epics::pvData::Mutex choicesMutex; epics::pvData::Event choicesEvent; epicsTimeStamp caTimeStamp; CaAlarm caAlarm; CaDisplay caDisplay; CaControl caControl; CaValueAlarm caValueAlarm; - std::string description; epics::pvData::Structure::const_shared_pointer structure; std::vector choices; };