void PVStructure::appendPVField( String const &fieldName, PVFieldPtr const & pvField) { size_t origLength = pvFields.size(); size_t newLength = origLength+1; PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields); xxx->push_back(pvField); FieldConstPtr field = getFieldCreate()->appendField( structurePtr,fieldName,pvField->getField()); replaceField(field); structurePtr = static_pointer_cast<const Structure>(field); StringArray fieldNames = structurePtr->getFieldNames(); for(size_t i=0; i<newLength; i++) { pvFields[i]->setParentAndName(this,fieldNames[i]); } fixParentStructure(); }
PVStructure::shared_pointer ValueBuilder::buildPVStructure() const { if(parent) THROW_EXCEPTION2(std::logic_error, "Only top level structure may be built. Missing endNested() ?"); StructureConstPtr type; { FieldBuilderPtr tbuild(getFieldCreate()->createFieldBuilder()); child_struct::buildStruct(*this, tbuild); type = tbuild->createStructure(); } PVStructure::shared_pointer root(type->build()); child_struct::storeStruct(*this, root); return root; }
RecordListRecordPtr RecordListRecord::create( std::string const & recordName) { FieldCreatePtr fieldCreate = getFieldCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate(); StructureConstPtr topStructure = fieldCreate->createFieldBuilder()-> addNestedStructure("argument")-> add("database",pvString)-> add("regularExpression",pvString)-> endNested()-> addNestedStructure("result") -> add("status",pvString) -> addArray("names",pvString) -> endNested()-> createStructure(); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure); RecordListRecordPtr pvRecord( new RecordListRecord(recordName,pvStructure)); if(!pvRecord->init()) pvRecord.reset(); return pvRecord; }
ExampleHelloPtr ExampleHello::create( string const & recordName) { StandardFieldPtr standardField = getStandardField(); FieldCreatePtr fieldCreate = getFieldCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate(); StructureConstPtr topStructure = fieldCreate->createFieldBuilder()-> addNestedStructure("argument")-> add("value",pvString)-> endNested()-> addNestedStructure("result") -> add("value",pvString) -> add("timeStamp",standardField->timeStamp()) -> endNested()-> createStructure(); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure); ExampleHelloPtr pvRecord( new ExampleHello(recordName,pvStructure)); if(!pvRecord->init()) pvRecord.reset(); return pvRecord; }
void PVStructure::fixParentStructure() { PVStructure *parent = getParent(); if(parent==NULL) return; StructureConstPtr parentStructure = parent->structurePtr; String fieldName = getFieldName(); size_t index = parentStructure->getFieldIndex(fieldName); StringArray const &fieldNames = parentStructure->getFieldNames(); size_t num = fieldNames.size(); FieldConstPtrArray fields(num); FieldConstPtrArray const & oldFields = parentStructure->getFields(); for(size_t i=0; i< num; i++) { if(i==index) { fields[i] = structurePtr; } else { fields[i] = oldFields[i]; } } FieldConstPtr field = getFieldCreate()->createStructure( parentStructure->getID(),fieldNames,fields); parent->replaceField(field); parent->fixParentStructure(); }
/** * Creates an NTURI request. * * @param path the value of the NTURI path field * @param fieldnames the names of fields in the NTURI query * @return values the values of fields in the NTURI query */ PVStructurePtr createRequest(const std::string & path, const std::vector<std::string> & fieldnames, const std::vector<std::string> & values) { StructureConstPtr archiverStructure = makeRequestStructure(*getFieldCreate(), fieldnames); PVStructurePtr request(getPVDataCreate()->createPVStructure(archiverStructure)); // set scheme. request->getStringField("scheme")->put("pva"); // set path. request->getStringField("path")->put(path); // Set query. PVStructurePtr query = request->getStructureField("query"); for (size_t i = 0; i < fieldnames.size(); ++i) { query->getStringField(fieldnames[i])->put(values[i]); } return request; }
void PVStructure::removePVField(String const &fieldName) { PVFieldPtr pvField = getSubField(fieldName); if(pvField.get()==NULL) { String message("removePVField "); message += fieldName + " does not exist"; this->message(message, errorMessage); return; } size_t origLength = pvFields.size(); size_t newLength = origLength - 1; PVFieldPtrArray const & origPVFields = pvFields; FieldConstPtrArray origFields = structurePtr->getFields(); PVFieldPtrArray newPVFields; newPVFields.reserve(newLength); StringArray newFieldNames; newFieldNames.reserve(newLength); FieldConstPtrArray fields; fields.reserve(newLength); for(size_t i=0; i<origLength; i++) { if(origPVFields[i]!=pvField) { newFieldNames.push_back(origPVFields[i]->getFieldName()); newPVFields.push_back(origPVFields[i]); fields.push_back(origFields[i]); } } PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields); xxx->swap(newPVFields); FieldConstPtr field = getFieldCreate()->createStructure( structurePtr->getID(),newFieldNames,fields); replaceField(field); structurePtr = static_pointer_cast<const Structure>(field); StringArray fieldNames = structurePtr->getFieldNames(); for(size_t i=0; i<newLength; i++) { pvFields[i]->setParentAndName(this,fieldNames[i]); } }
PVStructurePtr createPowerSupply() { FieldCreatePtr fieldCreate = getFieldCreate(); StandardFieldPtr standardField = getStandardField(); PVDataCreatePtr pvDataCreate = getPVDataCreate(); return pvDataCreate->createPVStructure( fieldCreate->createFieldBuilder()-> add("alarm",standardField->alarm()) -> add("timeStamp",standardField->timeStamp()) -> addNestedStructure("power") -> add("value",pvDouble) -> add("alarm",standardField->alarm()) -> endNested()-> addNestedStructure("voltage") -> add("value",pvDouble) -> add("alarm",standardField->alarm()) -> endNested()-> addNestedStructure("current") -> add("value",pvDouble) -> add("alarm",standardField->alarm()) -> endNested()-> createStructure()); }
PVDataCreate::PVDataCreate() : fieldCreate(getFieldCreate()) { }
namespace epics { namespace pvaClient { static FieldCreatePtr fieldCreate = getFieldCreate(); static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create(); PvaClientMultiChannelPtr PvaClientMultiChannel::create( PvaClientPtr const &pvaClient, epics::pvData::shared_vector<const string> const & channelNames, string const & providerName, size_t maxNotConnected) { return PvaClientMultiChannelPtr( new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected)); } PvaClientMultiChannel::PvaClientMultiChannel( PvaClientPtr const &pvaClient, epics::pvData::shared_vector<const string> const & channelName, string const & providerName, size_t maxNotConnected) : pvaClient(pvaClient), channelName(channelName), providerName(providerName), maxNotConnected(maxNotConnected), numChannel(channelName.size()), numConnected(0), pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())), isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)), createRequest(CreateRequest::create()), isDestroyed(false) { } PvaClientMultiChannel::~PvaClientMultiChannel() { destroy(); } void PvaClientMultiChannel::destroy() { { Lock xx(mutex); if(isDestroyed) return; isDestroyed = true; } pvaClientChannelArray.clear(); } void PvaClientMultiChannel::checkConnected() { if(numConnected==0){ Status status = connect(3.0); if(status.isOK()) return; throw std::runtime_error("pvaClientMultiChannel connect failure"); } } epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames() { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); return channelName; } Status PvaClientMultiChannel::connect(double timeout) { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); for(size_t i=0; i< numChannel; ++i) { pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName); pvaClientChannelArray[i]->issueConnect(); } Status returnStatus = Status::Ok; Status status = Status::Ok; size_t numBad = 0; for(size_t i=0; i< numChannel; ++i) { if(numBad==0) { status = pvaClientChannelArray[i]->waitConnect(timeout); } else { status = pvaClientChannelArray[i]->waitConnect(.001); } if(status.isOK()) { ++numConnected; isConnected[i] = true; continue; } if(returnStatus.isOK()) returnStatus = status; ++numBad; if(numBad>maxNotConnected) break; } return numBad>maxNotConnected ? returnStatus : Status::Ok; } bool PvaClientMultiChannel::allConnected() { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); return (numConnected==numChannel) ? true : false; } bool PvaClientMultiChannel::connectionChange() { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); for(size_t i=0; i<numChannel; ++i) { PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i]; Channel::shared_pointer channel = pvaClientChannel->getChannel(); Channel::ConnectionState stateNow = channel->getConnectionState(); bool connectedNow = stateNow==Channel::CONNECTED ? true : false; if(connectedNow!=isConnected[i]) return true; } return false; } epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected() { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); for(size_t i=0; i<numChannel; ++i) { PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i]; if(!pvaClientChannel) { isConnected[i] = false; continue; } Channel::shared_pointer channel = pvaClientChannel->getChannel(); Channel::ConnectionState stateNow = channel->getConnectionState(); isConnected[i] = (stateNow==Channel::CONNECTED) ? true : false; } return isConnected; } PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray() { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); return pvaClientChannelArray; } PvaClientPtr PvaClientMultiChannel::getPvaClient() { if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed"); return pvaClient; } PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet() { checkConnected(); return PvaClientMultiGetDouble::create(getPtrSelf(),pvaClientChannelArray); } PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut() { checkConnected(); return PvaClientMultiPutDouble::create(getPtrSelf(),pvaClientChannelArray); } PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor() { checkConnected(); return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray); } PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut() { checkConnected(); return PvaClientNTMultiPut::create(getPtrSelf(), pvaClientChannelArray); } PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet() { return createNTGet("value,alarm,timeStamp"); } PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request) { checkConnected(); PVStructurePtr pvRequest = createRequest->createRequest(request); if(!pvRequest) { string message = " PvaClientMultiChannel::createNTGet invalid pvRequest: " + createRequest->getMessage(); throw std::runtime_error(message); } return PvaClientNTMultiGet::create(getPtrSelf(), pvaClientChannelArray,pvRequest); } PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor() { return createNTMonitor("value,alarm,timeStamp"); } PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request) { checkConnected(); PVStructurePtr pvRequest = createRequest->createRequest(request); if(!pvRequest) { string message = " PvaClientMultiChannel::createNTMonitor invalid pvRequest: " + createRequest->getMessage(); throw std::runtime_error(message); } return PvaClientNTMultiMonitor::create(getPtrSelf(), pvaClientChannelArray,pvRequest); } }}
StandardPVField::StandardPVField() : standardField(getStandardField()), fieldCreate(getFieldCreate()), pvDataCreate(getPVDataCreate()), notImplemented("not implemented") {}
namespace epics { namespace nt { static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static NTFieldPtr ntField = NTField::get(); namespace detail { NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::value(UnionConstPtr valuePtr) { valueType = valuePtr; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addDescriptor() { descriptor = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addAlarm() { alarm = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addTimeStamp() { timeStamp = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSeverity() { severity = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addStatus() { status = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addMessage() { message = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSecondsPastEpoch() { secondsPastEpoch = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addNanoseconds() { nanoseconds = true; return shared_from_this(); } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addUserTag() { userTag = true; return shared_from_this(); } StructureConstPtr NTMultiChannelBuilder::createStructure() { StandardFieldPtr standardField = getStandardField(); size_t nfields = 3; size_t extraCount = extraFieldNames.size(); nfields += extraCount; if(descriptor) ++nfields; if(alarm) ++nfields; if(timeStamp) ++nfields; if(severity) ++nfields; if(status) ++nfields; if(message) ++nfields; if(secondsPastEpoch) ++nfields; if(nanoseconds) ++nfields; if(userTag) ++nfields; FieldConstPtrArray fields(nfields); StringArray names(nfields); size_t ind = 0; names[ind] = "value"; if(valueType) { fields[ind++] = fieldCreate->createUnionArray(valueType); } else { fields[ind++] = fieldCreate->createVariantUnionArray(); } names[ind] = "channelName"; fields[ind++] = fieldCreate->createScalarArray(pvString); names[ind] = "isConnected"; fields[ind++] = fieldCreate->createScalarArray(pvBoolean); if(timeStamp) { names[ind] = "timeStamp"; fields[ind++] = standardField->timeStamp(); } if(alarm) { names[ind] = "alarm"; fields[ind++] = standardField->alarm(); } if(descriptor) { names[ind] = "descriptor"; fields[ind++] = fieldCreate->createScalar(pvString); } if(severity) { names[ind] = "severity"; fields[ind++] = fieldCreate->createScalarArray(pvInt); } if(status) { names[ind] = "status"; fields[ind++] = fieldCreate->createScalarArray(pvInt); } if(message) { names[ind] = "message"; fields[ind++] = fieldCreate->createScalarArray(pvString); } if(secondsPastEpoch) { names[ind] = "secondsPastEpoch"; fields[ind++] = fieldCreate->createScalarArray(pvLong); } if(nanoseconds) { names[ind] = "nanoseconds"; fields[ind++] = fieldCreate->createScalarArray(pvInt); } if(userTag) { names[ind] = "userTag"; fields[ind++] = fieldCreate->createScalarArray(pvInt); } for (size_t i = 0; i< extraCount; i++) { names[ind] = extraFieldNames[i]; fields[ind++] = extraFields[i]; } StructureConstPtr st = fieldCreate->createStructure(NTMultiChannel::URI,names,fields); reset(); return st; } PVStructurePtr NTMultiChannelBuilder::createPVStructure() { return pvDataCreate->createPVStructure(createStructure()); } NTMultiChannelPtr NTMultiChannelBuilder::create() { return NTMultiChannelPtr(new NTMultiChannel(createPVStructure())); } NTMultiChannelBuilder::NTMultiChannelBuilder() { reset(); } void NTMultiChannelBuilder::reset() { valueType.reset(); extraFieldNames.clear(); extraFields.clear(); descriptor = false; alarm = false; timeStamp = false; severity = false; status = false; message = false; secondsPastEpoch = false; nanoseconds = false; userTag = false; } NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::add(string const & name, FieldConstPtr const & field) { extraFields.push_back(field); extraFieldNames.push_back(name); return shared_from_this(); } } const std::string NTMultiChannel::URI("epics:nt/NTMultiChannel:1.0"); NTMultiChannel::shared_pointer NTMultiChannel::wrap(PVStructurePtr const & structure) { if(!isCompatible(structure)) return shared_pointer(); return wrapUnsafe(structure); } NTMultiChannel::shared_pointer NTMultiChannel::wrapUnsafe(PVStructurePtr const & structure) { return shared_pointer(new NTMultiChannel(structure)); } bool NTMultiChannel::is_a(StructureConstPtr const &structure) { return NTUtils::is_a(structure->getID(), URI); } bool NTMultiChannel::isCompatible(PVStructurePtr const &pvStructure) { if(!pvStructure) return false; PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value"); if(!pvValue) return false; PVFieldPtr pvField = pvStructure->getSubField("descriptor"); if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false; pvField = pvStructure->getSubField("alarm"); if(pvField && !ntField->isAlarm(pvField->getField())) return false; pvField = pvStructure->getSubField("timeStamp"); if(pvField && !ntField->isTimeStamp(pvField->getField())) return false; pvField = pvStructure->getSubField("severity"); if(pvField && !pvStructure->getSubField<PVIntArray>("severity")) return false; pvField = pvStructure->getSubField("status"); if(pvField && !pvStructure->getSubField<PVIntArray>("status")) return false; pvField = pvStructure->getSubField("message"); if(pvField && !pvStructure->getSubField<PVStringArray>("message")) return false; pvField = pvStructure->getSubField("secondsPastEpoch"); if(pvField && !pvStructure->getSubField<PVLongArray>("secondsPastEpoch")) return false; pvField = pvStructure->getSubField("nanoseconds"); if(pvField && !pvStructure->getSubField<PVIntArray>("nanoseconds")) return false; pvField = pvStructure->getSubField("userTag"); if(pvField && !pvStructure->getSubField<PVIntArray>("userTag")) return false; return true; } NTMultiChannelBuilderPtr NTMultiChannel::createBuilder() { return NTMultiChannelBuilderPtr(new detail::NTMultiChannelBuilder()); } NTMultiChannel::NTMultiChannel(PVStructurePtr const & pvStructure) : pvNTMultiChannel(pvStructure), pvTimeStamp(pvStructure->getSubField<PVStructure>("timeStamp")), pvAlarm(pvStructure->getSubField<PVStructure>("alarm")), pvValue(pvStructure->getSubField<PVUnionArray>("value")), pvChannelName(pvStructure->getSubField<PVStringArray>("channelName")), pvIsConnected(pvStructure->getSubField<PVBooleanArray>("isConnected")), pvSeverity(pvStructure->getSubField<PVIntArray>("severity")), pvStatus(pvStructure->getSubField<PVIntArray>("status")), pvMessage(pvStructure->getSubField<PVStringArray>("message")), pvSecondsPastEpoch(pvStructure->getSubField<PVLongArray>("secondsPastEpoch")), pvNanoseconds(pvStructure->getSubField<PVIntArray>("nanoseconds")), pvUserTag(pvStructure->getSubField<PVIntArray>("userTag")), pvDescriptor(pvStructure->getSubField<PVString>("descriptor")) { } void NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) const { if(!pvTimeStamp) return; pv.attach(pvTimeStamp); } void NTMultiChannel::attachAlarm(PVAlarm &pv) const { if(!pvAlarm) return; pv.attach(pvAlarm); } }}
namespace epics { namespace pvaClient { static ConvertPtr convert = getConvert(); static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static StandardFieldPtr standardField = getStandardField(); PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create( PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) { PvaClientMultiMonitorDoublePtr pvaClientMultiMonitorDouble( new PvaClientMultiMonitorDouble(pvaMultiChannel,pvaClientChannelArray)); return pvaClientMultiMonitorDouble; } PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble( PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) : pvaClientMultiChannel(pvaClientMultiChannel), pvaClientChannelArray(pvaClientChannelArray), nchannel(pvaClientChannelArray.size()), doubleValue(shared_vector<double>(nchannel,epicsNAN)), pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())), isMonitorConnected(false), isDestroyed(false) { } PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble() { destroy(); } void PvaClientMultiMonitorDouble::destroy() { { Lock xx(mutex); if(isDestroyed) return; isDestroyed = true; } pvaClientChannelArray.clear(); } void PvaClientMultiMonitorDouble::connect() { shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); string request = "value"; for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request); pvaClientMonitor[i]->issueConnect(); } } for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { Status status = pvaClientMonitor[i]->waitConnect(); if(status.isOK()) continue; string message = string("channel ") + pvaClientChannelArray[i]->getChannelName() + " PvaChannelMonitor::waitConnect " + status.getMessage(); throw std::runtime_error(message); } } for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) pvaClientMonitor[i]->start(); } isMonitorConnected = true; } bool PvaClientMultiMonitorDouble::poll() { if(!isMonitorConnected){ connect(); epicsThreadSleep(.01); } bool result = false; shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { if(pvaClientMonitor[i]->poll()) { doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble(); pvaClientMonitor[i]->releaseEvent(); result = true; } } } return result; } bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent) { if(poll()) return true; TimeStamp start; start.getCurrent(); TimeStamp now; while(true) { epicsThreadSleep(.1); if(poll()) return true; now.getCurrent(); double diff = TimeStamp::diff(now,start); if(diff>=waitForEvent) break; } return false; } epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get() { return doubleValue; } }}
namespace epics { namespace pvaClient { static ConvertPtr convert = getConvert(); static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static StandardFieldPtr standardField = getStandardField(); static CreateRequest::shared_pointer createRequest = CreateRequest::create(); PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create( PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) { PvaClientMultiPutDoublePtr pvaClientMultiPutDouble( new PvaClientMultiPutDouble(pvaMultiChannel,pvaClientChannelArray)); return pvaClientMultiPutDouble; } PvaClientMultiPutDouble::PvaClientMultiPutDouble( PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) : pvaClientMultiChannel(pvaClientMultiChannel), pvaClientChannelArray(pvaClientChannelArray), nchannel(pvaClientChannelArray.size()), pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())), isPutConnected(false), isDestroyed(false) { } PvaClientMultiPutDouble::~PvaClientMultiPutDouble() { destroy(); } void PvaClientMultiPutDouble::destroy() { { Lock xx(mutex); if(isDestroyed) return; isDestroyed = true; } pvaClientChannelArray.clear(); } void PvaClientMultiPutDouble::connect() { shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { pvaClientPut[i] = pvaClientChannelArray[i]->createPut(); pvaClientPut[i]->issueConnect(); } } for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { Status status = pvaClientPut[i]->waitConnect(); if(status.isOK()) continue; string message = string("channel ") + pvaClientChannelArray[i]->getChannelName() + " PvaChannelPut::waitConnect " + status.getMessage(); throw std::runtime_error(message); } } isPutConnected = true; } void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data) { if(!isPutConnected) connect(); if(data.size()!=nchannel) { throw std::runtime_error("data has wrong size"); } shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure(); PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value"); convert->fromDouble(pvValue,data[i]); pvaClientPut[i]->issuePut(); } if(isConnected[i]) { Status status = pvaClientPut[i]->waitPut(); if(status.isOK()) continue; string message = string("channel ") + pvaClientChannelArray[i]->getChannelName() + " PvaChannelPut::waitPut " + status.getMessage(); throw std::runtime_error(message); } } } }}
StandardField::StandardField() : fieldCreate(getFieldCreate()), notImplemented("not implemented"), valueFieldName("value") {}
namespace detail { static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static Mutex mutex; StructureConstPtr NTNDArrayBuilder::createStructure() { enum { DISCRIPTOR_INDEX, TIMESTAMP_INDEX, ALARM_INDEX, DISPLAY_INDEX }; const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1; const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES; Lock xx(mutex); static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES]; static UnionConstPtr valueType; static StructureConstPtr codecStruc; static StructureConstPtr dimensionStruc; static StructureConstPtr attributeStruc; StructureConstPtr returnedStruc; size_t index = 0; if (descriptor) index |= 1 << DISCRIPTOR_INDEX; if (timeStamp) index |= 1 << TIMESTAMP_INDEX; if (alarm) index |= 1 << ALARM_INDEX; if (display) index |= 1 << DISPLAY_INDEX; bool isExtended = !extraFieldNames.empty(); if (isExtended || !ntndarrayStruc[index]) { StandardFieldPtr standardField = getStandardField(); FieldBuilderPtr fb = fieldCreate->createFieldBuilder(); if (!valueType) { for (int i = pvBoolean; i < pvString; ++i) { ScalarType st = static_cast<ScalarType>(i); fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st); } valueType = fb->createUnion(); } if (!codecStruc) { codecStruc = fb->setId("codec_t")-> add("name", pvString)-> add("parameters", fieldCreate->createVariantUnion())-> createStructure(); } if (!dimensionStruc) { dimensionStruc = fb->setId("dimension_t")-> add("size", pvInt)-> add("offset", pvInt)-> add("fullSize", pvInt)-> add("binning", pvInt)-> add("reverse", pvBoolean)-> createStructure(); } if (!attributeStruc) { attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure(); } fb->setId(NTNDArray::URI)-> add("value", valueType)-> add("codec", codecStruc)-> add("compressedSize", pvLong)-> add("uncompressedSize", pvLong)-> addArray("dimension", dimensionStruc)-> add("uniqueId", pvInt)-> add("dataTimeStamp", standardField->timeStamp())-> addArray("attribute", attributeStruc); if (descriptor) fb->add("descriptor", pvString); if (alarm) fb->add("alarm", standardField->alarm()); if (timeStamp) fb->add("timeStamp", standardField->timeStamp()); if (display) fb->add("display", standardField->display()); size_t extraCount = extraFieldNames.size(); for (size_t i = 0; i< extraCount; i++) fb->add(extraFieldNames[i], extraFields[i]); returnedStruc = fb->createStructure(); if (!isExtended) ntndarrayStruc[index] = returnedStruc; } else { return ntndarrayStruc[index]; } return returnedStruc; } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor() { descriptor = true; return shared_from_this(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm() { alarm = true; return shared_from_this(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp() { timeStamp = true; return shared_from_this(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay() { display = true; return shared_from_this(); } PVStructurePtr NTNDArrayBuilder::createPVStructure() { return getPVDataCreate()->createPVStructure(createStructure()); } NTNDArrayPtr NTNDArrayBuilder::create() { return NTNDArrayPtr(new NTNDArray(createPVStructure())); } NTNDArrayBuilder::NTNDArrayBuilder() { reset(); } void NTNDArrayBuilder::reset() { descriptor = false; timeStamp = false; alarm = false; display = false; extraFieldNames.clear(); extraFields.clear(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::add(string const & name, FieldConstPtr const & field) { extraFields.push_back(field); extraFieldNames.push_back(name); return shared_from_this(); } }
namespace epics { namespace nt { static NTFieldPtr ntField = NTField::get(); namespace detail { static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static Mutex mutex; StructureConstPtr NTNDArrayBuilder::createStructure() { enum { DISCRIPTOR_INDEX, TIMESTAMP_INDEX, ALARM_INDEX, DISPLAY_INDEX }; const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1; const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES; Lock xx(mutex); static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES]; static UnionConstPtr valueType; static StructureConstPtr codecStruc; static StructureConstPtr dimensionStruc; static StructureConstPtr attributeStruc; StructureConstPtr returnedStruc; size_t index = 0; if (descriptor) index |= 1 << DISCRIPTOR_INDEX; if (timeStamp) index |= 1 << TIMESTAMP_INDEX; if (alarm) index |= 1 << ALARM_INDEX; if (display) index |= 1 << DISPLAY_INDEX; bool isExtended = !extraFieldNames.empty(); if (isExtended || !ntndarrayStruc[index]) { StandardFieldPtr standardField = getStandardField(); FieldBuilderPtr fb = fieldCreate->createFieldBuilder(); if (!valueType) { for (int i = pvBoolean; i < pvString; ++i) { ScalarType st = static_cast<ScalarType>(i); fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st); } valueType = fb->createUnion(); } if (!codecStruc) { codecStruc = fb->setId("codec_t")-> add("name", pvString)-> add("parameters", fieldCreate->createVariantUnion())-> createStructure(); } if (!dimensionStruc) { dimensionStruc = fb->setId("dimension_t")-> add("size", pvInt)-> add("offset", pvInt)-> add("fullSize", pvInt)-> add("binning", pvInt)-> add("reverse", pvBoolean)-> createStructure(); } if (!attributeStruc) { attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure(); } fb->setId(NTNDArray::URI)-> add("value", valueType)-> add("codec", codecStruc)-> add("compressedSize", pvLong)-> add("uncompressedSize", pvLong)-> addArray("dimension", dimensionStruc)-> add("uniqueId", pvInt)-> add("dataTimeStamp", standardField->timeStamp())-> addArray("attribute", attributeStruc); if (descriptor) fb->add("descriptor", pvString); if (alarm) fb->add("alarm", standardField->alarm()); if (timeStamp) fb->add("timeStamp", standardField->timeStamp()); if (display) fb->add("display", standardField->display()); size_t extraCount = extraFieldNames.size(); for (size_t i = 0; i< extraCount; i++) fb->add(extraFieldNames[i], extraFields[i]); returnedStruc = fb->createStructure(); if (!isExtended) ntndarrayStruc[index] = returnedStruc; } else { return ntndarrayStruc[index]; } return returnedStruc; } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor() { descriptor = true; return shared_from_this(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm() { alarm = true; return shared_from_this(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp() { timeStamp = true; return shared_from_this(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay() { display = true; return shared_from_this(); } PVStructurePtr NTNDArrayBuilder::createPVStructure() { return getPVDataCreate()->createPVStructure(createStructure()); } NTNDArrayPtr NTNDArrayBuilder::create() { return NTNDArrayPtr(new NTNDArray(createPVStructure())); } NTNDArrayBuilder::NTNDArrayBuilder() { reset(); } void NTNDArrayBuilder::reset() { descriptor = false; timeStamp = false; alarm = false; display = false; extraFieldNames.clear(); extraFields.clear(); } NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::add(string const & name, FieldConstPtr const & field) { extraFields.push_back(field); extraFieldNames.push_back(name); return shared_from_this(); } } const std::string NTNDArray::URI("epics:nt/NTNDArray:1.0"); const std::string ntAttrStr("epics:nt/NTAttribute:1.0"); static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); class NTValueType { public: static bool isCompatible(UnionConstPtr const &u) { if(!u.get()) return false; if (u->getID() != Union::defaultId()) return false; if (u->isVariant()) return false; for (int i = pvBoolean; i != pvString; ++i) { ScalarType scalarType = static_cast<ScalarType>(i); std::string name(ScalarTypeFunc::name(scalarType)); name += "Value"; ScalarArrayConstPtr scalarField = u->getField<ScalarArray>(name); if (scalarField.get() == 0 || scalarField->getElementType() != scalarType) return false; } return true; } }; class NTCodec { public: static bool isCompatible(StructureConstPtr const &structure) { if(!structure.get()) return false; if (structure->getID() != "codec_t") return false; ScalarConstPtr scalarField = structure->getField<Scalar>("name"); if (scalarField.get() == 0 || scalarField->getScalarType() != pvString) return false; UnionConstPtr paramField = structure->getField<Union>("parameters"); if (paramField.get() == 0 || !paramField->isVariant()) return false; return true; } }; class NTDimension { public: static bool isCompatible(StructureConstPtr const &structure) { if(!structure.get()) return false; if (structure->getID() != "dimension_t") return false; ScalarConstPtr scalarField = structure->getField<Scalar>("size"); if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) return false; scalarField = structure->getField<Scalar>("offset"); if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) return false; scalarField = structure->getField<Scalar>("fullSize"); if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) return false; scalarField = structure->getField<Scalar>("binning"); if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) return false; scalarField = structure->getField<Scalar>("reverse"); if (scalarField.get() == 0 || scalarField->getScalarType() != pvBoolean) return false; return true; } }; NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & pvStructure) { if(!isCompatible(pvStructure)) return shared_pointer(); return wrapUnsafe(pvStructure); } NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & pvStructure) { return shared_pointer(new NTNDArray(pvStructure)); } bool NTNDArray::is_a(StructureConstPtr const & structure) { return NTUtils::is_a(structure->getID(), URI); } bool NTNDArray::isCompatible(StructureConstPtr const &structure) { if(!structure.get()) return false; UnionConstPtr valueField = structure->getField<Union>("value"); if(!NTValueType::isCompatible(valueField)) return false; StructureConstPtr codecField = structure->getField<Structure>("codec"); if(!NTCodec::isCompatible(codecField)) return false; ScalarConstPtr compressedSizeField = structure->getField<Scalar>("compressedSize"); if (compressedSizeField.get() == 0) return false; if (compressedSizeField->getScalarType() != pvLong) return false; ScalarConstPtr uncompressedSizeField = structure->getField<Scalar>("uncompressedSize"); if (uncompressedSizeField.get() == 0) return false; if (uncompressedSizeField->getScalarType() != pvLong) return false; StructureArrayConstPtr dimensionField = structure->getField<StructureArray>("dimension"); if (dimensionField.get() == 0) return false; StructureConstPtr dimElementStruc = dimensionField->getStructure(); if(!NTDimension::isCompatible(dimElementStruc)) return false; NTFieldPtr ntField = NTField::get(); StructureConstPtr dataTimeStampField = structure->getField<Structure>( "dataTimeStamp"); if (dataTimeStampField.get() == 0 || !ntField->isTimeStamp(dataTimeStampField)) return false; ScalarConstPtr uniqueIdField = structure->getField<Scalar>("uniqueId"); if (uniqueIdField.get() == 0) return false; if (uniqueIdField->getScalarType() != pvInt) return false; StructureArrayConstPtr attributeField = structure->getField<StructureArray>( "attribute"); StructureConstPtr attributeElementStruc = attributeField->getStructure(); if (!NTNDArrayAttribute::isCompatible(attributeElementStruc)) return false; FieldConstPtr field = structure->getField("descriptor"); if (field.get()) { ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor"); if (!descriptorField.get() || descriptorField->getScalarType() != pvString) return false; } field = structure->getField("alarm"); if (field.get() && !ntField->isAlarm(field)) return false; field = structure->getField("timeStamp"); if (field.get() && !ntField->isTimeStamp(field)) return false; field = structure->getField("display"); if (field.get() && !ntField->isDisplay(field)) return false; return true; } bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure) { if(!pvStructure.get()) return false; return isCompatible(pvStructure->getStructure()); } bool NTNDArray::isValid() { int64 valueSize = getValueSize(); int64 compressedSize = getCompressedDataSize()->get(); if (valueSize != compressedSize) return false; long expectedUncompressed = getExpectedUncompressedSize(); long uncompressedSize = getUncompressedDataSize()->get(); if (uncompressedSize != expectedUncompressed) return false; std::string codecName = getCodec()->getSubField<PVString>("name")->get(); if (codecName == "" && valueSize < uncompressedSize) return false; return true; } int64 NTNDArray::getExpectedUncompressedSize() { int64 size = 0; PVStructureArrayPtr pvDim = getDimension(); if (pvDim->getLength() != 0) { PVStructureArray::const_svector data = pvDim->view(); size = getValueTypeSize(); for (PVStructureArray::const_svector::const_iterator it = data.begin(); it != data.end(); ++it ) { PVStructurePtr dim = *it; size *= dim->getSubField<PVInt>("size")->get(); } } return size; } int64 NTNDArray::getValueSize() { int64 size = 0; PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>(); if (!storedValue.get()) { size = storedValue->getLength()*getValueTypeSize(); } return size; } int64 NTNDArray::getValueTypeSize() { int64 typeSize = 0; PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>(); if (storedValue.get()) { switch (storedValue->getScalarArray()->getElementType()) { case pvBoolean: case pvByte: case pvUByte: typeSize = 1; break; case pvShort: case pvUShort: typeSize = 2; break; case pvInt: case pvUInt: case pvFloat: typeSize = 4; break; case pvLong: case pvULong: case pvDouble: typeSize = 8; break; default: break; } } return typeSize; } NTNDArrayBuilderPtr NTNDArray::createBuilder() { return NTNDArrayBuilderPtr(new detail::NTNDArrayBuilder()); } bool NTNDArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const { PVStructurePtr ts = getTimeStamp(); if (ts) return pvTimeStamp.attach(ts); else return false; } bool NTNDArray::attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const { PVStructurePtr ts = getDataTimeStamp(); if (ts) return pvTimeStamp.attach(ts); else return false; } bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const { PVStructurePtr al = getAlarm(); if (al) return pvAlarm.attach(al); else return false; } bool NTNDArray::attachDisplay(PVDisplay &pvDisplay) const { PVStructurePtr dp = getDisplay(); if (dp) return pvDisplay.attach(dp); else return false; } PVStructurePtr NTNDArray::getPVStructure() const { return pvNTNDArray; } PVUnionPtr NTNDArray::getValue() const { return pvNTNDArray->getSubField<PVUnion>("value"); } PVStructurePtr NTNDArray::getCodec() const { return pvNTNDArray->getSubField<PVStructure>("codec"); } PVLongPtr NTNDArray::getCompressedDataSize() const { return pvNTNDArray->getSubField<PVLong>("compressedSize"); } PVLongPtr NTNDArray::getUncompressedDataSize() const { return pvNTNDArray->getSubField<PVLong>("uncompressedSize"); } PVStructureArrayPtr NTNDArray::getDimension() const { return pvNTNDArray->getSubField<PVStructureArray>("dimension"); } PVIntPtr NTNDArray::getUniqueId() const { return pvNTNDArray->getSubField<PVInt>("uniqueId"); } PVStructurePtr NTNDArray::getDataTimeStamp() const { return pvNTNDArray->getSubField<PVStructure>("dataTimeStamp"); } PVStructureArrayPtr NTNDArray::getAttribute() const { return pvNTNDArray->getSubField<PVStructureArray>("attribute"); } PVStringPtr NTNDArray::getDescriptor() const { return pvNTNDArray->getSubField<PVString>("descriptor"); } PVStructurePtr NTNDArray::getTimeStamp() const { return pvNTNDArray->getSubField<PVStructure>("timeStamp"); } PVStructurePtr NTNDArray::getAlarm() const { return pvNTNDArray->getSubField<PVStructure>("alarm"); } PVStructurePtr NTNDArray::getDisplay() const { return pvNTNDArray->getSubField<PVStructure>("display"); } NTNDArray::NTNDArray(PVStructurePtr const & pvStructure) : pvNTNDArray(pvStructure) {} }}