/// /// \file instant.cpp /// \author Jan Chrin, PSI /// \date Release: February 2015 /// \version CAFE 1.0.0 /// #ifndef INSTANT_CPP #define INSTANT_CPP /** * \brief Set values of data type CTYPE * \param _handle input: handle to CAFEConduit object * \param _dbrType input: chtype * \param _val value/array of values of datatype const CTYPE * \return ECA_NORMAL if all OK else CAFE_ or ECA_ error * \return CAFE_ error if CAFEConduit::putCallback() operation is not to be executed: * \return ECAFE_INVALID_HANDLE - Invalid reference handle * \return ECAFE_NOWTACCESS - Write access denied * \return ICAFE_CA_OP_CONN_DOWN - Channel is not connected * \return ECA_ error from CAFEConduit::putCallback() operation: * \return (*) should not arise due to pre-checks * \return ECA_NORMAL - Normal successful completion * \return ECA_BADCHID - Corrupted Channel Identifier (chid) * \return ECA_BADTYPE (*) - Invalid DBR_XXX type * \return ECA_BADCOUNT (*) - Requested count larger than native element count * \return ECA_NOWTACCESS (*) - Write access denied * \return ECA_ALLOCMEM - Unable to allocate memory * \return ECA_DISCONN (*) - Channel is disconnected */ template int Instant::set(const unsigned int _handle, const chtype _dbrType, const CTYPE * _val ) { #define __METHOD__ "Instant::set(_handle, _dbrType, _val)" status=ICAFE_NORMAL; if (_dbrType > DBR_DOUBLE) { std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl; std::cout << "INTERNAL CAFE ERROR: HOW DID THIS PERCULIAR DATA TYPE: " << dbr_type_to_text(_dbrType) << " GET THROUGH!" << endl; } cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(_handle); if (it_handle != handle_index.end()) { if ( (status=cafeGranules.channelVerifyPut(_handle, _dbrType)) != ICAFE_NORMAL) { return status; } if ( (status=cafeGranules.channelPreparePut(_handle)) != ICAFE_NORMAL) { return status; } if ( (status=clientRequests(_handle, _dbrType, _val)) != ICAFE_NORMAL) { return status; } if ( (status=cafeGranules.channelExecutePut(_handle)) != ICAFE_NORMAL) { return status; } } else { cout << __FILE__ << "/" << __LINE__ << "/" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); return ECAFE_INVALID_HANDLE; } if(MUTEX) {cafeMutex.lock();}; //lock handle_index.modify(it_handle, change_status(status)); if(MUTEX) {cafeMutex.unlock();}; //unlock return status; #undef __METHOD__ } /** * \brief Retrieve values of data type CTYPE * \param _handle input: handle to CAFEConduit object * \param _dbrType input: chtype * \param _val output: value/array of values of datatype const CTYPE * \param alarmStatus output * \param alarmSeverity output * \param ts output: epicsTimeStamp * \return ECA_NORMAL if all OK else CAFE_ or ECA_ error * \return CAFE_ error if CAFEConduit::get() operation is not to be executed: * \return ECAFE_INVALID_HANDLE - Invalid reference handle * \return ECAFE_NORDACCESS - Read access denied * \return ICAFE_CA_OP_CONN_DOWN - Channel is not connected * \return ECA_ error from CAFEConduit::get() operation: * \return (*) should not arise due to pre-checks * \return ECA_NORMAL - Normal successful completion * \return ECA_BADCHID - Corrupted Channel Identifier (chid) * \return ECA_BADTYPE (*) - Invalid DBR_XXX type * \return ECA_BADCOUNT (*) - Requested count larger than native element count * \return ECA_NORDACCESS(*)- Read access denied * \return ECA_ALLOCMEM - Unable to allocate memory * \return ECA_DISCONN (*) - Channel is disconnected */ template int Instant::get(const unsigned int _handle, const chtype _dbrType, CTYPE * _val, dbr_short_t &alarmStatus, dbr_short_t &alarmSeverity, epicsTimeStamp &ts) { #define __METHOD__ "Instant::get(_handle, dbrType, _val, alarmStatus, alarmSeverity, ts) " //cout << __FILE__ << " " << __LINE__ << " " << __METHOD__ << endl; status=ICAFE_NORMAL; if (_dbrType > DBR_CTRL_DOUBLE) { std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl; std::cout << "INTERNAL CAFE ERROR: HOW DID THIS PERCULIAR DATA TYPE: " << dbr_type_to_text(_dbrType) << " GET THROUGH!" << endl; } else if (_dbrType > DBR_TIME_DOUBLE) { std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl; std::cout << "INTERNAL CAFE ERROR: METHOD NOT MEANT FOR THIS DATA TYPE: " << dbr_type_to_text(_dbrType) << endl; std::cout << "CAFE WILL THUS TAKE CONTROL OF ALLOCATING APPROPIATE DBR_TYPE" << endl; } cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(_handle); if (it_handle != handle_index.end()) { if ( (*it_handle).getChannelGetActionWhenMonitorPolicy().getActionKind() == CAFENUM::GET_FROM_CACHE) { if ( helper.getNmonitorData(_handle) >0){ return Instant::getCache(_handle, _dbrType, _val, alarmStatus, alarmSeverity, ts); } } if ( (status=cafeGranules.channelVerifyGet(_handle, _dbrType)) != ICAFE_NORMAL) { return status; } //Here fill channelRequestMetaData if ( (status=cafeGranules.channelPrepareGet(_handle)) != ICAFE_NORMAL) { return status; } if ( (status=cafeGranules.channelExecuteGet(_handle)) != ICAFE_NORMAL) { return status; } channelRequestMetaDataClient = (*it_handle).getChannelRequestMetaDataClient(); status=clientRequests( _handle, channelRequestMetaDataClient.getDbrDataType(), _val, alarmStatus, alarmSeverity, ts, false); } else { cout << __FILE__ << "/" << __LINE__ << "/" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); return ECAFE_INVALID_HANDLE; } if(MUTEX) {cafeMutex.lock();}; //lock handle_index.modify(it_handle, change_status(status)); if(MUTEX) {cafeMutex.unlock();}; //unlock return status; #undef __METHOD__ } /** * \brief Retrieve cached values of data type CTYPE * \param _handle input: handle to CAFEConduit object * \param _dbrType input: chtype * \param _val output: value/array of values of datatype const CTYPE * \param alarmStatus output * \param alarmSeverity output * \param ts output: epicsTimeStamp * \return ECA_NORMAL if all OK else CAFE_ or ECA_ error * \return CAFE_ error if CAFEConduit::get() operation is not to be executed: * \return ECAFE_INVALID_HANDLE - Invalid reference handle * \return ECAFE_NORDACCESS - Read access denied * \return ICAFE_CA_OP_CONN_DOWN - Channel is not connected * \return ECA_ error from CAFEConduit::get() operation: * \return (*) should not arise due to pre-checks * \return ECA_NORMAL - Normal successful completion * \return ECA_BADCHID - Corrupted Channel Identifier (chid) * \return ECA_BADTYPE (*) - Invalid DBR_XXX type * \return ECA_BADCOUNT (*) - Requested count larger than native element count * \return ECA_NORDACCESS(*)- Read access denied * \return ECA_ALLOCMEM - Unable to allocate memory * \return ECA_DISCONN (*) - Channel is disconnected */ template int Instant::getCache(const unsigned int _handle, const chtype _dbrType, CTYPE * _val, dbr_short_t &alarmStatus, dbr_short_t &alarmSeverity, epicsTimeStamp &ts) { #define __METHOD__ "Instant::getCache(_handle, dbrType, _val, alarmStatus, alarmSeverity, ts) " //cout << __FILE__ << " " << __LINE__ << " " << __METHOD__ << endl; status=ICAFE_NORMAL; ts.secPastEpoch= 0; // default value if cache does not have timeStamp ts.nsec = 0; // default value if cache does not have timeStamp alarmStatus =-1; // default value if cache does not have alarmStatus alarmSeverity =-1; // default value if cache does not have alarmSeverity cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(_handle); if (it_handle != handle_index.end()) { //cout << __METHOD__ << "__" << __LINE__ << endl; //cout << "(*it_handle).getChannelGetCacheWaitPolicy().getWaitKind()" << //(*it_handle).getChannelGetCacheWaitPolicy().getWaitKind() << " 0=NO_CHECK 1=NO_WAIT 2=WAIT " << endl; //meant for use in callbacks in monitors! if ( (*it_handle).getChannelGetCacheWaitPolicy().getWaitKind() == CAFENUM::GET_CACHE_NO_CHECK) { status=clientRequests(_handle, _dbrType, _val, alarmStatus, alarmSeverity, ts, true); return status; } //ifNeverConnected - return error if ( (*it_handle).getChannelRegalia().getCafeConnectionState() == ICAFE_CS_NEVER_CONN) { return ICAFE_CS_NEVER_CONN; } else if ( (*it_handle).getChannelRegalia().getCafeConnectionState()==ICAFE_CS_CLOSED) { return ICAFE_CS_CLOSED; } if (_dbrType > DBR_CTRL_DOUBLE) { std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl; std::cout << "INTERNAL CAFE ERROR: HOW DID THIS PERCULIAR DATA TYPE: " << dbr_type_to_text(_dbrType) << " GET THROUGH!" << endl; } else if (_dbrType > DBR_TIME_DOUBLE) { std::cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << std::endl; std::cout << "INTERNAL CAFE ERROR: METHOD NOT MEANT FOR THIS DATA TYPE: " << dbr_type_to_text(_dbrType) << endl; std::cout << "CAFE WILL THUS TAKE CONTROL OF ALLOCATING APPROPIATE DBR_TYPE" << endl; } chtype dbrtype =(*it_handle).getChannelRequestMetaData().getDbrDataType(); //MetaData will have true DBR_XXX_YYY type //Client is asking from cache for DBR_MMM_NNN //Therefore have to prepare DBR_MMM_NNN from DBR_XXX_YY CAFENUM::DBR_TYPE cafedbrtype= (*it_handle).getChannelRequestMetaData().getCafeDbrType(); switch (cafedbrtype) { case CAFENUM::DBR_TIME: dbrtype = dbf_type_to_DBR_TIME(_dbrType%DBR_STS_STRING); break; case CAFENUM::DBR_STS: dbrtype = dbf_type_to_DBR_STS(_dbrType%DBR_STS_STRING); break; case CAFENUM::DBR_PRIMITIVE: dbrtype = dbf_type_to_DBR(_dbrType%DBR_STS_STRING); break; default: dbrtype = (*it_handle).getChannelRequestMetaData().getDbrDataType(); cout << __METHOD__ << "/" << __LINE__ < int Instant::getCache(const unsigned int *handleArray, const unsigned int nelem, const chtype _dbrType, CTYPE * val, int *statusArray, dbr_short_t *alarmStatus, dbr_short_t *alarmSeverity, epicsTimeStamp *ts) { #define __METHOD__ "Instant::getCache(handleArray, nelem, _dbrType, val, statusArray) " unsigned int nelemPrevious=1; HandleHelper helper; int gStatus=ICAFE_NORMAL; bool statusSet=false; //cout << __FILE__ << " " << __LINE__ << " " << __METHOD__ << endl; for (unsigned int i=0; i (); cafeConduit_set_by_handle::iterator it_handle; it_handle = handle_index.find(handleArray[i]); channelRequestStatusGet =(*it_handle).getChannelRequestStatusGet(); if (channelRequestStatusGet.getCallbackProgressKind() == CAFENUM::PENDING && helper.getNmonitorData(handleArray[i])==0 && (*it_handle).getChannelRequestPolicyGet().getMethodKind() != CAFENUM::WITH_CALLBACK_USER_SUPPLIED && (*it_handle).getChannelGetCacheWaitPolicy().getWaitKind() == CAFENUM::GET_CACHE_WAIT && (*it_handle).isConnected() ) { channelTimeoutPolicyGet = (*it_handle).getChannelTimeoutPolicyGet(); ca_flush_io(); status=cafeGranules.waitForGetEvent(handleArray[i], channelTimeoutPolicyGet.getTimeout()); if (status==ECAFE_TIMEOUT && channelTimeoutPolicyGet.getSelfGoverningTimeout()) { unsigned short ntries=0; while (status==ECAFE_TIMEOUT && ntries int Instant::set(const unsigned int *handleArray, const unsigned int nelem, const chtype _dbrType, const CTYPE * val, int *statusArray) { #define __METHOD__ \ "Instant::set(unsigned int *handleArray, unsigned int nelem, const chtype _dbrType, dbr_double_t * val, int *statusArray)" int overallStatus=ICAFE_NORMAL; bool isGood=true; unsigned int nelemPrevious=1; for (unsigned int i=0; i int Instant::clientRequests( const unsigned int _handle, const chtype _dbrType, const CTYPE * _val) { #define __METHOD__ "Instant::clientRequests(*it_handle, _dbrType, _val)" cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; status=ICAFE_NORMAL; it_handle = handle_index.find(_handle); if (it_handle != handle_index.end()) { union db_access_val * PVDataL; unsigned int nelem; //unsigned int offset; chtype dbrTypeRequest_DataBuffer; PVDataL = (*it_handle).getPutBuffer (); nelem = (*it_handle).getChannelRequestMetaPrimitive().getNelem(); dbrTypeRequest_DataBuffer = (*it_handle).getChannelRequestMetaPrimitive().getDbrDataType(); switch(_dbrType) { case DBR_STRING: status=renderString.putString(_handle, (dbr_string_t *) _val); break; case DBR_SHORT: status=renderShort.put(_handle, (dbr_short_t *) _val, _dbrType ); break; case DBR_FLOAT: status=renderFloat.put(_handle, (dbr_float_t *) _val, _dbrType); break; case DBR_ENUM: status=renderEnum.put(_handle, (dbr_enum_t *) _val, _dbrType); break; case DBR_CHAR: status=renderChar.put(_handle, (dbr_char_t *) _val, _dbrType); break; case DBR_LONG: status=renderLong.put(_handle, (dbr_long_t *) _val, _dbrType); break; case DBR_DOUBLE: status=renderDouble.put(_handle, (dbr_double_t *) _val, _dbrType); break; default: cout << "ERROR: " << __FILE__ << "/" << __LINE__ << "/" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_SWITCH_CASE); cout << "SWITCH STATMENT NOT MEANT FOR CAFE DATATYPE=" << _dbrType < int Instant::setAndGet(const unsigned int handleSet, const chtype dbrType, CTYPE valSet, CTYPE &valGet) { #define __METHOD__ "Instant::setAndGet(const unsigned int handleSet,const chtype dbrType, CTYPE valSet, CTYPE &valGet" //CheckPolicy CTYPE valGetA[1]; CTYPE valSetA[1]; valGetA[0]=0; valGet=0; valSetA[0] = (CTYPE) valSet; status=Instant::set(handleSet, dbrType, valSetA); if (status==ICAFE_NORMAL) { unsigned int nelemPrevious, nelemRequestedCheck=0; unsigned int nelemRequested=1; nelemPrevious=helper.getNelemClient(handleSet); //Check the number of elements requested? if (nelemPrevious>1) { nelemRequestedCheck = helper.setNelem(handleSet,nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } status=Instant::get(handleSet, dbrType, valGetA); if (nelemPrevious>1) { helper.setNelem(handleSet,nelemPrevious); } valGet=valGetA[0]; } else { return status; } if(valSet==valGet) { return ICAFE_NORMAL; } cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Process Variable = " << helper.getPVFromHandle(handleSet) << endl; cout << "Set Value: " << valSet << " Get Value: " << valGet << endl; return ICAFE_SET_AND_GET_MISMATCH; #undef __METHOD__ } template int Instant::setMany(vector handleSet, const chtype dbrType, vector valSet, bool printFlag) { #define __METHOD__ "Instant::setMany(vectorhandleSet, chtype, vectorvalSet)" CAFEStatus cstat; CTYPE valSetA[1]; status=ICAFE_NORMAL; if (handleSet.size() != valSet.size() ) { return ECAFE_HANDLE_MISMATCH_SET_AND_MATCH; } for (size_t i=0; i< handleSet.size(); ++i) { if (!helper.isChannelConnected(handleSet[i])) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "NOT ALL CHANNELS CONNECTED: " << endl; if (!helper.isChannelConnected(handleSet[i])) { helper.printHandle(handleSet[i]); status=helper.getStatus(handleSet[i]); } } } if (status!=ICAFE_NORMAL) {return status;} if(printFlag) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; } if (printFlag) { for (size_t i=0; i< handleSet.size(); ++i) { if (dbrType==DBR_CHAR) { cout << "SETTING PV=" << helper.getPVFromHandle(handleSet[i]) << " to " << (unsigned short) valSet[i] << endl; } else { cout << "SETTING PV=" << helper.getPVFromHandle(handleSet[i]) << " to " << valSet[i] << endl; } } //for } //if for (size_t i=0; i< handleSet.size(); ++i) { //set No of Elements to 1 unsigned int nelemPrevious, nelemRequestedCheck=0; unsigned int nelemRequested=1; nelemPrevious=helper.getNelemClient(handleSet[i]); //Check the number of elements requested? if (nelemPrevious>1) { nelemRequestedCheck = helper.setNelem(handleSet[i],nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } //policy set synchronous ChannelRequestPolicy polPrevious, polNow; policyHelper.getChannelRequestPolicyPut(handleSet[i], polPrevious); polNow.setMethodKind(WITHOUT_CALLBACK); polNow.setWaitKind(WAIT); polNow.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); policyHelper.setChannelRequestPolicyPut(handleSet[i], polNow); valSetA[0] = (CTYPE) valSet[i]; status=set(handleSet[i], dbrType, valSetA); if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } policyHelper.setChannelRequestPolicyPut(handleSet[i], polPrevious); unsigned int nelemPreviousCheck=nelemPrevious; nelemRequested=1; //Switch back to previous value //if (nelemPrevious>1) { if(helper.getNelemRequest(handleSet[i])!= nelemPrevious) { nelemPreviousCheck= helper.setNelem(handleSet[i],nelemPrevious); if (nelemPreviousCheck != nelemPrevious) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPrevious << " but got instead: " << nelemPreviousCheck << endl; } } } //for size_t return status; } #undef __METHOD__ /** * \brief Set Channels followed by a corresponding readback of Channels \n * Method verifies whether or not the set/readback values agree within the given tolerance and timeout \n * Method returns with ECA_NORMAL as soon as a match is reached * \param handleSet input: vector of handleSet * \param dbrType input: chtype of set value * \param valSet input: vector of CTYPE values to set * \param handleMatch input: vector of handles of readback channel * \param tolerance input: CTYPE of tolerance margin * \param timeout input: double value; maximum time allowed for agreement to occur * \param printFlag input: bool, set to true for diagnostics * \return ECA_NORMAL if all OK, else first ECAFE error encountered, else ECAFE_TIMEOUT_SET_AND_MATCH */ template int Instant::compareAndMatchMany(vector handleSet, const chtype dbrType, vector valSet, vector handleMatch, CTYPE tolerance, double timeout, bool printFlag){ //template int Instant::setTriggerAndMatchMany(vector handleSet, chtype dbrType, vector valSet, // vector handleAction, vector valAction, vector handleMatch, // CTYPE tolerance, double timeout, bool printFlag){ #define __METHOD__ "Instant::compareAndMatchMany(chtype, vectorvalSet, vectorhandleMatch, tolerance, timeout, printFlag)" Connect connect; CAFEStatus cstat; CTYPE valGetA[1]; //CTYPE valSetA[1]; status=ICAFE_NORMAL; if (handleMatch.size() != valSet.size() ) { return ECAFE_HANDLE_MISMATCH_SET_AND_MATCH; } for (size_t i=0; i< handleMatch.size(); ++i) { if (!helper.isChannelConnected(handleMatch[i])) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "NOT ALL CHANNELS CONNECTED: " << endl; if (!helper.isChannelConnected(handleMatch[i])) {helper.printHandle(handleMatch[i]); status=helper.getStatus(handleMatch[i]);} } } if (status!=ICAFE_NORMAL) {return status;} if(printFlag) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; } if (printFlag) { for (size_t i=0; i< handleMatch.size(); ++i) { if (dbrType==DBR_CHAR) { cout << "SETTING PV= " << helper.getPVFromHandle(handleSet[i]) << " to " << (unsigned short) valSet[i] << endl; } else { cout << "SETTING PV= " << helper.getPVFromHandle(handleSet[i]) << " to " << valSet[i] << endl; } cout << "READBACK PV=" << helper.getPVFromHandle(handleMatch[i]) << " tolerance= " << fabs( (double) tolerance) << endl; cout << "TIME ALLOWED FOR MATCH IS " << timeout << " (sec) " << endl; } //for } //if vector valSetUpper; vector valSetLower; vector monitorID; vector statMonitor; vector nMonitors; vector valGet; vector nelemPreviousCache; valSetUpper.reserve( valSet.size()); valSetLower.reserve( valSet.size()); monitorID.reserve( valSet.size()); statMonitor.reserve( valSet.size()); valGet.reserve( valSet.size()); nMonitors.reserve( valSet.size() ); nelemPreviousCache.reserve( valSet.size()); for (size_t i=0; i< valSet.size(); ++i) { switch (dbrType) { case DBR_LONG : case DBR_SHORT : case DBR_ENUM: valSetUpper[i] = valSet[i] + abs((int)tolerance); valSetLower[i] = valSet[i] - abs((int)tolerance); break; case DBR_CHAR : valSetUpper[i] = (unsigned short) valSet[i] + abs((unsigned short) tolerance); valSetLower[i] = (unsigned short) valSet[i] - abs((unsigned short) tolerance); break; case DBR_FLOAT: case DBR_DOUBLE: default: valSetUpper[i] = (CTYPE) (valSet[i] + fabs((double)tolerance)); valSetLower[i] = (CTYPE) (valSet[i] - fabs((double)tolerance)); break; } vector mpVMatch; mpVMatch.clear(); helper.getMonitorPolicyVector(handleMatch[i], mpVMatch); nMonitors[i]=mpVMatch.size(); monitorID[i]=0; ////valGetA[0][i]=0; valGet[i]=0; statMonitor[i]=ICAFE_NORMAL; } for (size_t i=0; i< handleMatch.size(); ++i) { //what is monitorpolicy?? if (nMonitors[i]==0) { unsigned int _nelemPrevious, _nelemRequestedCheck=0; unsigned int _nelemRequested=1; _nelemPrevious=helper.getNelemClient(handleMatch[i]); //Check the number of elements requested? if (_nelemPrevious>1) { _nelemRequestedCheck = helper.setNelem(handleMatch[i],_nelemRequested); if (_nelemRequestedCheck != _nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << _nelemPrevious << endl; cout << "to: " << _nelemRequested << " but got instead: " << _nelemRequestedCheck << endl; } } //first do get to update cache before monitor starts status=Instant::get(handleMatch[i], dbrType, valGetA); valGet[i]=valGetA[0]; if (_nelemPrevious>1) { helper.setNelem(handleMatch[i],_nelemPrevious); } if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ChannelWhenToFlushSendBufferPolicyKind whenKind= connect.channelMonitorPolicy.getWhenToFlushSendBuffer(); connect.channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); statMonitor[i]=connect.monitorStart(handleMatch[i], monitorID[i]); if (statMonitor[i]!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(statMonitor[i]); } else { if(printFlag) {cout << "MONITOR NOW IN PLACE FOR READBACK CHANNEL " << helper.getPVFromHandle(handleMatch[i]) << " WITH ID=" << monitorID[i] << endl;} } //revert to previous if (whenKind != FLUSH_AUTOMATIC) { connect.channelMonitorPolicy.setWhenToFlushSendBuffer(whenKind); } } //if nMonitors //No of elements to get from Cache //unsigned int nelemPreviousCheck=0; unsigned int nelemRequested=1; unsigned int nelemRequestedCheck=0; nelemPreviousCache[i]=helper.getNelemRequest(handleMatch[i]); //Check the number of elements requested //See set and Match; this needs to be checked //Avoid problem when readback channel is the very same as the set(!) if (nelemPreviousCache[i]>0 && helper.getNelemNative(handleMatch[i])>1) { nelemRequestedCheck = helper.setNelemToRetrieveFromCache(handleMatch[i],nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPreviousCache[i] << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } } //for size_t //start time double timeElapsed=0; double timeElapsed2=0; double timeElapsedBase=0; using namespace boost::posix_time; ptime timeStart(microsec_clock::local_time()); for (size_t i=0; i< handleMatch.size(); ++i) { valGetA[0]=0; status=Instant::getCache(handleMatch[i], dbrType, valGetA); valGet[i]=valGetA[0]; if (status !=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ///valGet[i]=valGetA[0][i]; if (dbrType==DBR_CHAR) {valGet[i] = (unsigned short) valGetA[0];} if(printFlag) { //cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; if (dbrType==DBR_CHAR) { cout << "Current Cached Value = " << (unsigned short) valGet[i] << endl; cout << "Lower/Upper Target Values = " << (unsigned short) valSetLower[i] << " and " << (unsigned short) valSetUpper[i] << endl; } else { cout << "Current Cached Value = " << valGet[i] << endl; cout << "Lower/Upper Target Values = " << valSetLower[i] << " and " << valSetUpper[i] << endl; } } } //for size_t ptime timeEnd(microsec_clock::local_time()); time_duration duration(timeEnd-timeStart); timeElapsed= (double) duration.total_microseconds()/1000000.0; for (size_t i=0; i< valSet.size(); ++i) { while ( (valGet[i]>valSetUpper[i] || valGet[i]1 && status==ICAFE_NORMAL) { for (size_t ij=0; ij< handleMatch.size(); ++ij) { status=Instant::getCache(handleMatch[ij], dbrType, valGetA); valGet[ij]=valGetA[0]; if (valGet[ij]>valSetUpper[ij] || valGet[ij]1) { nelemPreviousCheck= helper.setNelemToRetrieveFromCache(handleMatch[i],nelemPreviousCache[i]); if (nelemPreviousCheck != nelemPreviousCache[i]) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPreviousCache[i] << " but got instead: " << nelemPreviousCheck << endl; } } if (nMonitors[i]==0 && statMonitor[i]==ICAFE_NORMAL && printFlag) { cout << "MONITOR NOW STOPPED FOR READBACK CHANNEL " << helper.getPVFromHandle(handleMatch[i]) << " WITH ID =" << monitorID[i] << endl; int statm; statm=connect.monitorStop(handleMatch[i], monitorID[i]); if (status==ICAFE_NORMAL) {status=statm;} } } //for return status; #undef __METHOD__ } /** * \brief Set Channels followed by a corresponding readback of Channels \n * Method verifies whether or not the set/readback values agree within the given tolerance and timeout \n * Method returns with ECA_NORMAL as soon as a match is reached * \param handleSet input: vector of handleSet * \param dbrType input: chtype of set value * \param valSet input: vector of CTYPE values to set * \param handleMatch input: vector of handles of readback channel * \param tolerance input: CTYPE of tolerance margin * \param timeout input: double value; maximum time allowed for agreement to occur * \param printFlag input: bool, set to true for diagnostics * \return ECA_NORMAL if all OK, else first ECAFE error encountered, else ECAFE_TIMEOUT_SET_AND_MATCH */ template int Instant::setAndMatchMany(vector handleSet, chtype dbrType, vector valSet, vector handleMatch, CTYPE tolerance, double timeout, bool printFlag){ #define __METHOD__ "Instant::setAndMatchMany(vectorhandleSet, chtype, vectorvalSet, vectorhandleMatch, tolerance, timeout, printFlag)" Connect connect; CAFEStatus cstat; CTYPE valGetA[1]; CTYPE valSetA[1]; status=ICAFE_NORMAL; if (handleSet.size() != handleMatch.size() ) { return ECAFE_HANDLE_MISMATCH_SET_AND_MATCH; } if (handleSet.size() != valSet.size() ) { return ECAFE_HANDLE_MISMATCH_SET_AND_MATCH; } for (size_t i=0; i< handleSet.size(); ++i) { if (!helper.isChannelConnected(handleSet[i]) || !helper.isChannelConnected(handleMatch[i])) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "NOT ALL CHANNELS CONNECTED: " << endl; if (!helper.isChannelConnected(handleSet[i])) {helper.printHandle(handleSet[i]); status=helper.getStatus(handleSet[i]);} if (!helper.isChannelConnected(handleMatch[i])) {helper.printHandle(handleMatch[i]); status=helper.getStatus(handleMatch[i]);} } } if (status!=ICAFE_NORMAL) {return status;} if(printFlag) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; } for (size_t i=0; i< handleSet.size(); ++i) { if (printFlag) { if (dbrType==DBR_CHAR) { cout << "SETTING PV=" << helper.getPVFromHandle(handleSet[i]) << " to " << (unsigned short) valSet[i] << endl; } else { cout << "SETTING PV=" << helper.getPVFromHandle(handleSet[i]) << " to " << valSet[i] << endl; } cout << "READBACK PV=" << helper.getPVFromHandle(handleMatch[i]) << " tolerance= " << fabs( (double) tolerance) << endl; cout << "TIME ALLOWED FOR MATCH IS " << timeout << " (sec) " << endl; } } vector valSetUpper; vector valSetLower; vector monitorID; vector statMonitor; vector nMonitors; vector valGet; vector nelemPreviousCache; valSetUpper.reserve( handleSet.size()); valSetLower.reserve( handleSet.size()); monitorID.reserve( handleSet.size()); statMonitor.reserve( handleSet.size()); valGet.reserve( handleSet.size()); nMonitors.reserve( handleSet.size() ); nelemPreviousCache.reserve(handleSet.size()); for (size_t i=0; i< handleSet.size(); ++i) { switch (dbrType) { case DBR_LONG : case DBR_SHORT : case DBR_ENUM: valSetUpper[i] = valSet[i] + abs((int)tolerance); valSetLower[i] = valSet[i] - abs((int)tolerance); break; case DBR_CHAR : valSetUpper[i] = (unsigned short) valSet[i] + abs((unsigned short) tolerance); valSetLower[i] = (unsigned short) valSet[i] - abs((unsigned short) tolerance); break; case DBR_FLOAT: case DBR_DOUBLE: default: valSetUpper[i] = (CTYPE) (valSet[i] + fabs((double)tolerance)); valSetLower[i] = (CTYPE) (valSet[i] - fabs((double)tolerance)); break; } vector mpVMatch; mpVMatch.clear(); helper.getMonitorPolicyVector(handleMatch[i], mpVMatch); nMonitors[i]=mpVMatch.size(); monitorID[i]=0; ////valGetA[0][i]=0; valGet[i]=0; statMonitor[i]=ICAFE_NORMAL; } for (size_t i=0; i< handleSet.size(); ++i) { //what is monitorpolicy?? if (nMonitors[i]==0) { unsigned int _nelemPrevious, _nelemRequestedCheck=0; unsigned int _nelemRequested=1; _nelemPrevious=helper.getNelemClient(handleMatch[i]); //Check the number of elements requested? if (_nelemPrevious>1) { _nelemRequestedCheck = helper.setNelem(handleMatch[i],_nelemRequested); //change handleSet to handleMatch 23/3/17 if (_nelemRequestedCheck != _nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << _nelemPrevious << endl; cout << "to: " << _nelemRequested << " but got instead: " << _nelemRequestedCheck << endl; } } //first do get to update cache before monitor starts status=Instant::get(handleMatch[i], dbrType, valGetA); valGet[i]=valGetA[0]; if (_nelemPrevious>1) { helper.setNelem(handleMatch[i],_nelemPrevious); //change handleSet to handleMatch 23/3/17 } if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ChannelWhenToFlushSendBufferPolicyKind whenKind= connect.channelMonitorPolicy.getWhenToFlushSendBuffer(); connect.channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); statMonitor[i]=connect.monitorStart(handleMatch[i], monitorID[i]); if (statMonitor[i]!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(statMonitor[i]); } else { if(printFlag) {cout << "MONITOR NOW IN PLACE FOR READBACK CHANNEL " << helper.getPVFromHandle(handleMatch[i]) << " WITH ID=" << monitorID[i] << endl;} } //revert to previous if (whenKind != FLUSH_AUTOMATIC) { connect.channelMonitorPolicy.setWhenToFlushSendBuffer(whenKind); } } //if nMonitors ////valSetA[0][i]=valSet[i]; //set No of Elements to 1 unsigned int nelemPrevious, nelemRequestedCheck=0; unsigned int nelemRequested=1; nelemPrevious=helper.getNelemClient(handleSet[i]); //Check the number of elements requested? if (nelemPrevious>1) { nelemRequestedCheck = helper.setNelem(handleSet[i],nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } //policy set synchronous ChannelRequestPolicy polPrevious, polNow; policyHelper.getChannelRequestPolicyPut(handleSet[i], polPrevious); polNow.setMethodKind(WITHOUT_CALLBACK); polNow.setWaitKind(WAIT); polNow.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); policyHelper.setChannelRequestPolicyPut(handleSet[i], polNow); valSetA[0] = (CTYPE) valSet[i]; status=set(handleSet[i], dbrType, valSetA); if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } policyHelper.setChannelRequestPolicyPut(handleSet[i], polPrevious); unsigned int nelemPreviousCheck=nelemPrevious; nelemRequested=1; //Switch back to previous value //if (nelemPrevious>1) { if(helper.getNelemRequest(handleSet[i])!= nelemPrevious) { nelemPreviousCheck= helper.setNelem(handleSet[i],nelemPrevious); if (nelemPreviousCheck != nelemPrevious) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPrevious << " but got instead: " << nelemPreviousCheck << endl; } } //No of elements to get from Cache nelemPreviousCheck=0; nelemRequested=1; nelemRequestedCheck=0; nelemPreviousCache[i]=helper.getNelemRequest(handleMatch[i]); //Check the number of elements requested //See set and Match; this needs to be checked //Avoid problem when readback channel is the very same as the set(!) if (nelemPreviousCache[i]>0 && helper.getNelemNative(handleMatch[i])>1) { nelemRequestedCheck = helper.setNelemToRetrieveFromCache(handleMatch[i],nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPreviousCache[i] << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } } //for size_t //start time double timeElapsed=0; double timeElapsed2=0; double timeElapsedBase=0; using namespace boost::posix_time; ptime timeStart(microsec_clock::local_time()); for (size_t i=0; i< handleSet.size(); ++i) { valGetA[0]=0; status=Instant::getCache(handleMatch[i], dbrType, valGetA); valGet[i]=valGetA[0]; if (status !=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ///valGet[i]=valGetA[0][i]; if (dbrType==DBR_CHAR) {valGet[i] = (unsigned short) valGetA[0];} if(printFlag) { //cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; if (dbrType==DBR_CHAR) { cout << "Current Cached Value = " << (unsigned short) valGet[i] << endl; cout << "Lower/Upper Target Values = " << (unsigned short) valSetLower[i] << " and " << (unsigned short) valSetUpper[i] << endl; } else { cout << "Current Cached Value = " << valGet[i] << endl; cout << "Lower/Upper Target Values = " << valSetLower[i] << " and " << valSetUpper[i] << endl; } } } //for size_t ptime timeEnd(microsec_clock::local_time()); time_duration duration(timeEnd-timeStart); timeElapsed= (double) duration.total_microseconds()/1000000.0; for (size_t i=0; i< handleSet.size(); ++i) { while ( (valGet[i]>valSetUpper[i] || valGet[i]1 && status==ICAFE_NORMAL) { for (size_t ij=0; ij< handleMatch.size(); ++ij) { status=Instant::getCache(handleMatch[ij], dbrType, valGetA); valGet[ij]=valGetA[0]; if (valGet[ij]>valSetUpper[ij] || valGet[ij]1) { nelemPreviousCheck= helper.setNelemToRetrieveFromCache(handleMatch[i],nelemPreviousCache[i]); if (nelemPreviousCheck != nelemPreviousCache[i]) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPreviousCache[i] << " but got instead: " << nelemPreviousCheck << endl; } } if (nMonitors[i]==0 && statMonitor[i]==ICAFE_NORMAL && printFlag) { cout << "MONITOR NOW STOPPED FOR READBACK CHANNEL " << helper.getPVFromHandle(handleMatch[i]) << " WITH ID =" << monitorID[i] << endl; int statm; statm=connect.monitorStop(handleMatch[i], monitorID[i]); if (status==ICAFE_NORMAL) {status=statm;} } } //for return status; #undef __METHOD__ } /** * \brief Set Channel 1 followed by a readback of Channel 2 \n * Method verifies whether or not the 2 values agree within the given tolerance and timeout \n * Method returns with ECA_NORMAL as soon as a match is reached * \param handleSet input: handleSet * \param dbrType input: chtype of set value * \param valSet input: CTYPE value to set * \param handleMatch input: handle of readback channel * \param tolerance input: CTYPE of tolerance margin * \param timeout input: double value; maximum time allowed for agreement to occur * \param printFlag input: bool, set to true for diagnostics * \return ECA_NORMAL if all OK else first ECAFE error encountered */ template int Instant::setAndMatch(const unsigned int handleSet, const chtype dbrType, CTYPE valSet, const unsigned int handleMatch, CTYPE tolerance, double timeout, bool printFlag){ #define __METHOD__ "Instant::setAndMatch(handleSet, dbrType, valSet, handleMatch, tolerance, timeout, printFlag)" //check both handles exists before proceeding Connect connect; CAFEStatus cstat; if (!helper.isChannelConnected(handleSet) || !helper.isChannelConnected(handleMatch)) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "NOT ALL CHANNELS CONNECTED: " << endl; if (!helper.isChannelConnected(handleSet)) {helper.printHandle(handleSet); return helper.getStatus(handleSet);} if (!helper.isChannelConnected(handleMatch)) {helper.printHandle(handleMatch); return helper.getStatus(handleMatch);} } if (printFlag) { if (dbrType==DBR_CHAR) { cout << "SETTING PV=" << helper.getPVFromHandle(handleSet) << " to " << (unsigned short) valSet << endl; } else { cout << "SETTING PV=" << helper.getPVFromHandle(handleSet) << " to " << valSet << endl; } cout << "READBACK PV=" << helper.getPVFromHandle(handleMatch) << " tolerance= " << fabs((double)tolerance) << endl; cout << "TIME ALLOWED FOR MATCH " << timeout << " (sec) " << endl; } vector mpVMatch; helper.getMonitorPolicyVector(handleMatch, mpVMatch); unsigned short nMonitors=mpVMatch.size(); CTYPE valSetUpper; CTYPE valSetLower; switch (dbrType) { case DBR_LONG : case DBR_SHORT : case DBR_ENUM: valSetUpper = valSet + abs((int)tolerance); valSetLower = valSet - abs((int)tolerance); break; case DBR_CHAR : valSetUpper = (unsigned short) valSet + abs((unsigned short) tolerance); valSetLower = (unsigned short) valSet - abs((unsigned short) tolerance); break; case DBR_FLOAT: case DBR_DOUBLE: default: valSetUpper = (CTYPE) (valSet + fabs((double)tolerance)); valSetLower = (CTYPE) (valSet - fabs((double)tolerance)); break; } CTYPE valGetA[1]={0}; CTYPE valGet=valGetA[0]; int statMonitor=ICAFE_NORMAL; unsigned int monitorIDis=0; //what is monitorpolicy?? if (nMonitors==0) { unsigned int _nelemPrevious, _nelemRequestedCheck=0; unsigned int _nelemRequested=1; _nelemPrevious=helper.getNelemClient(handleMatch); //Check the number of elements requested? if (_nelemPrevious>1) { _nelemRequestedCheck = helper.setNelem(handleMatch,_nelemRequested); ////change handleSet to handleMatch 23/3/17 if (_nelemRequestedCheck != _nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << _nelemPrevious << endl; cout << "to: " << _nelemRequested << " but got instead: " << _nelemRequestedCheck << endl; } } //first do get to update cache before monitor starts status=Instant::get(handleMatch, dbrType, valGetA); //valGet=valGetA[0]; if (_nelemPrevious>1) { helper.setNelem(handleMatch,_nelemPrevious); ////change handleSet to handleMatch 23/3/17 } if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ChannelWhenToFlushSendBufferPolicyKind whenKind= connect.channelMonitorPolicy.getWhenToFlushSendBuffer(); connect.channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); statMonitor=connect.monitorStart(handleMatch, monitorIDis); if (statMonitor!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(statMonitor); } else { if(printFlag) {cout << "MONITOR STARTED WITH ID=" << monitorIDis<< endl;} } //revert to previous if (whenKind != FLUSH_AUTOMATIC) { connect.channelMonitorPolicy.setWhenToFlushSendBuffer(whenKind); } } CTYPE valSetA[1]; valSetA[0]=valSet; //set No of Elements to 1 unsigned int nelemPrevious, nelemRequestedCheck=0; unsigned int nelemRequested=1; nelemPrevious=helper.getNelemClient(handleSet); //Check the number of elements requested? if (nelemPrevious>1) { nelemRequestedCheck = helper.setNelem(handleSet,nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } //policy set synchronous ChannelRequestPolicy polPrevious, polNow; policyHelper.getChannelRequestPolicyPut(handleSet, polPrevious); polNow.setMethodKind(WITHOUT_CALLBACK); polNow.setWaitKind(WAIT); polNow.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); policyHelper.setChannelRequestPolicyPut(handleSet, polNow); status=set(handleSet, dbrType, valSetA); if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } policyHelper.setChannelRequestPolicyPut(handleSet, polPrevious); unsigned int nelemPreviousCheck=nelemPrevious; nelemRequested=1; //Switch back to previous value //if (nelemPrevious>1) { if(helper.getNelemRequest(handleSet)!= nelemPrevious) { nelemPreviousCheck= helper.setNelem(handleSet,nelemPrevious); if (nelemPreviousCheck != nelemPrevious) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPrevious << " but got instead: " << nelemPreviousCheck << endl; } } //start time double timeElapsed=0; double timeElapsed2=0; double timeElapsedBase=0; using namespace boost::posix_time; ptime timeStart(microsec_clock::local_time()); // PVDataHolder pvdMatch; // status=getCache(handleMatch, dbrType, pvdMatch); //No of elements to get from Cache nelemPreviousCheck=0; nelemRequested=1; nelemRequestedCheck=0; nelemPrevious=helper.getNelemRequest(handleMatch); //Check the number of elements requested if (nelemPrevious>0) { nelemRequestedCheck = helper.setNelemToRetrieveFromCache(handleMatch,nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } status=Instant::getCache(handleMatch, dbrType, valGetA); ///if (dbrType==DBR_CHAR) {valGet = (unsigned short) valGetA[0];} if (status !=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } if(printFlag) { //cout << __METHOD__ << endl; cout << "Current Cached Value = " ; if (dbrType==DBR_CHAR) { cout << (unsigned short) valGetA[0] << endl; cout << "Lower/Upper Target Values = " << (unsigned short) valSetLower << " and " << (unsigned short) valSetUpper << endl; } else { cout << valGetA[0] << endl; cout << "Lower/Upper Target Values = " << valSetLower << " and " << valSetUpper << endl; } } ptime timeEnd(microsec_clock::local_time()); time_duration duration(timeEnd-timeStart); timeElapsed= (double) duration.total_microseconds()/1000000.0; if (dbrType==DBR_CHAR) {valGet= (unsigned short) valGetA[0];} else { valGet=valGetA[0];} while ( (valGet>valSetUpper || valGetvalSetUpper || pvdMatch.getAsDouble()1) { nelemRequestedCheck = helper.setNelemToRetrieveFromCache(handleMatch,nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } */ status=Instant::getCache(handleMatch, dbrType, valGetA); valGet=valGetA[0]; if (dbrType==DBR_CHAR) {valGet = (unsigned short) valGetA[0];} //cout << "getCache(handleMatch, dbrType, valGetA) = " << valGet << endl; //cout << valSetUpper << " U/L " << valSetLower << endl; ptime timeEnd(microsec_clock::local_time()); time_duration duration(timeEnd-timeStart); timeElapsed= (double) duration.total_microseconds()/1000000.0; timeElapsed2=timeElapsed-timeElapsedBase; if (printFlag && timeElapsed2>1 && status==ICAFE_NORMAL) { if (dbrType==DBR_CHAR) { cout << "SET VALUE " << (unsigned short) valSet << " CURRENT VALUE " << (unsigned short) valGetA[0] << " TimeElapsed " << timeElapsed << " (sec) " << endl; } else { cout << "SET VALUE " << valSet << " CURRENT VALUE " << valGetA[0] //pvdMatch.getAsDouble() << " TimeElapsed " << timeElapsed << " (sec) " << endl; } timeElapsedBase=timeElapsed; } #if HAVE_BOOST_THREAD boost::this_thread::sleep_for(boost::chrono::microseconds(20)); #else #if HAVE_LINUX usleep(20); #endif #endif } if (timeout <=timeElapsed ) { cout << "*****TIMEOUT REACHED****** AFTER " << timeout << " (sec) " << endl; status=ECAFE_TIMEOUT_SET_AND_MATCH; } else { if (printFlag) { status=Instant::getCache(handleMatch, dbrType, valGetA); if (dbrType==DBR_CHAR) { cout << "GAME SET AND MATCH: SET VALUE= " << (unsigned short) valSet << " LAST VALUE READ= " << (unsigned short) valGetA[0] //pvdMatch.getAsDouble() << " TimeElapsed " << timeElapsed << " (sec) " << endl; } else { cout << "GAME SET AND MATCH: SET VALUE= " << valSet << " LAST VALUE READ= " << valGetA[0] //pvdMatch.getAsDouble() << " TimeElapsed " << timeElapsed << " (sec) " << endl; } } } if (nelemPrevious>1) { nelemPreviousCheck= helper.setNelemToRetrieveFromCache(handleMatch,nelemPrevious); if (nelemPreviousCheck != nelemPrevious) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPrevious << " but got instead: " << nelemPreviousCheck << endl; } } if (nMonitors==0 && statMonitor==ICAFE_NORMAL) { if (monitorIDis !=0 ) { cout << "STOPPED MONITOR WITH ID =" << monitorIDis << endl; int statm; statm=connect.monitorStop(handleMatch, monitorIDis); if (status==ICAFE_NORMAL) {status=statm;} } } return status; #undef __METHOD__ } /** * \brief Set Channel followed by a corresponding readback of Channel \n * Method verifies whether or not the set/readback values agree within the given tolerance and timeout \n * Method returns with ECA_NORMAL as soon as a match is reached * \param dbrType input: chtype of set value * \param valSet input: CTYPE value to set * \param handleMatch input: handle of readback channel * \param tolerance input: CTYPE of tolerance margin * \param timeout input: double value; maximum time allowed for agreement to occur * \param printFlag input: bool, set to true for diagnostics * \return ECA_NORMAL if all OK else first ECAFE error encountered */ template int Instant::match(const chtype dbrType, CTYPE valSet, unsigned int handleMatch, CTYPE tolerance, double timeout, bool printFlag){ #define __METHOD__ "Instant::match(const chtype dbrType, CTYPE valSet, unsigned int handleMatch, \ CTYPE tolerance,double timeout, bool printFlag)" vector valSetV; vectorhandleMatchV; valSetV.reserve(1); handleMatchV.reserve(1); valSetV.push_back(valSet); handleMatchV.push_back(handleMatch); return matchMany(dbrType, valSetV, handleMatchV, tolerance, timeout, printFlag); #undef __METHOD__ } /** * \brief Set Channels followed by a corresponding readback of Channels \n * Method verifies whether or not the set/readback values agree within the given tolerance and timeout \n * Method returns with ECA_NORMAL as soon as a match is reached * \param dbrType input: chtype of set value * \param valSet input: vector of CTYPE values to set * \param handleMatch input: vector of handles of readback channel * \param tolerance input: CTYPE of tolerance margin * \param timeout input: double value; maximum time allowed for agreement to occur * \param printFlag input: bool, set to true for diagnostics * \return ECA_NORMAL if all OK else first ECAFE error encountered */ template int Instant::matchMany(const chtype dbrType, vector valSet, vector handleMatch, CTYPE tolerance, double timeout, bool printFlag){ #define __METHOD__ "Instant::matchMany(const chtype dbrType, vectorvalSet, vectorhandleMatch, \ CTYPE tolerance, double timeout, bool printFlag)" Connect connect; CAFEStatus cstat; CTYPE valGetA[1]; ////CTYPE valSetA[1]; status=ICAFE_NORMAL; if (handleMatch.size() != valSet.size() ) { return ECAFE_HANDLE_MISMATCH_SET_AND_MATCH; } for (size_t i=0; i< handleMatch.size(); ++i) { if ( !helper.isChannelConnected(handleMatch[i])) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "NOT ALL CHANNELS CONNECTED: " << endl; helper.printHandle(handleMatch[i]); status=helper.getStatus(handleMatch[i]); } } if (status!=ICAFE_NORMAL) {return status;} for (size_t i=0; i< handleMatch.size(); ++i) { if (printFlag) { cout << "SET VALUE IS = " << valSet[i] << endl; cout << "READBACK PV=" << helper.getPVFromHandle(handleMatch[i]) << " tolerance= " << fabs((double)tolerance) << endl; cout << "TIME ALLOWED FOR MATCH IS " << timeout << " (sec) " << endl; } } vector valSetUpper; vector valSetLower; vector monitorID; vector statMonitor; vector nMonitors; vector valGet; vector nelemPreviousCache; valSetUpper.reserve( handleMatch.size()); valSetLower.reserve( handleMatch.size()); monitorID.reserve( handleMatch.size()); statMonitor.reserve( handleMatch.size()); valGet.reserve( handleMatch.size()); nMonitors.reserve( handleMatch.size() ); nelemPreviousCache.reserve(handleMatch.size()); for (size_t i=0; i< handleMatch.size(); ++i) { switch (dbrType) { case DBR_LONG : case DBR_SHORT : case DBR_ENUM: valSetUpper[i] = valSet[i] + abs((int)tolerance); valSetLower[i] = valSet[i] - abs((int)tolerance); break; case DBR_CHAR : valSetUpper[i] = (unsigned short) valSet[i] + abs((unsigned short) tolerance); valSetLower[i] = (unsigned short) valSet[i] - abs((unsigned short) tolerance); break; case DBR_FLOAT: case DBR_DOUBLE: default: valSetUpper[i] = (CTYPE) (valSet[i] + fabs((double)tolerance)); valSetLower[i] = (CTYPE) (valSet[i] - fabs((double)tolerance)); break; } vector mpVMatch; mpVMatch.clear(); helper.getMonitorPolicyVector(handleMatch[i], mpVMatch); nMonitors[i]=mpVMatch.size(); monitorID[i]=0; ////valGetA[0][i]=0; valGet[i]=0; statMonitor[i]=ICAFE_NORMAL; } for (size_t i=0; i< handleMatch.size(); ++i) { //what is monitorpolicy?? if (nMonitors[i]==0) { unsigned int _nelemPrevious, _nelemRequestedCheck=0; unsigned int _nelemRequested=1; _nelemPrevious=helper.getNelemClient(handleMatch[i]); //Check the number of elements requested? if (_nelemPrevious>1) { _nelemRequestedCheck = helper.setNelem(handleMatch[i],_nelemRequested); if (_nelemRequestedCheck != _nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << _nelemPrevious << endl; cout << "to: " << _nelemRequested << " but got instead: " << _nelemRequestedCheck << endl; } } //first do get to update cache before monitor starts status=Instant::get(handleMatch[i], dbrType, valGetA); valGet[i]=valGetA[0]; if (_nelemPrevious>1) { helper.setNelem(handleMatch[i],_nelemPrevious); } if (status!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ChannelWhenToFlushSendBufferPolicyKind whenKind= connect.channelMonitorPolicy.getWhenToFlushSendBuffer(); connect.channelMonitorPolicy.setWhenToFlushSendBuffer(FLUSH_AUTOMATIC); statMonitor[i]=connect.monitorStart(handleMatch[i], monitorID[i]); if (statMonitor[i]!=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(statMonitor[i]); } else { if(printFlag) {cout << "MONITOR STARTED WITH ID=" << monitorID[i] << endl;} } //revert to previous if (whenKind != FLUSH_AUTOMATIC) { connect.channelMonitorPolicy.setWhenToFlushSendBuffer(whenKind); } } //if nMonitors ////valSetA[0][i]=valSet[i]; //set No of Elements to 1 unsigned int nelemPrevious, nelemRequestedCheck=0; unsigned int nelemRequested=1; nelemPrevious=helper.getNelemClient(handleMatch[i]); //Check the number of elements requested? if (nelemPrevious>1) { nelemRequestedCheck = helper.setNelem(handleMatch[i],nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPrevious << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } //No of elements to get from Cache ////unsigned int nelemPreviousCheck=0; nelemRequested=1; nelemRequestedCheck=0; nelemPreviousCache[i]=helper.getNelemRequest(handleMatch[i]); //Check the number of elements requested //See set and Match; this needs to be checked //Avoid problem when readback channel is the very same as the set(!) if (nelemPreviousCache[i]>0 && helper.getNelemNative(handleMatch[i])>1) { nelemRequestedCheck = helper.setNelemToRetrieveFromCache(handleMatch[i],nelemRequested); if (nelemRequestedCheck != nelemRequested) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to set the no. elements from: " << nelemPreviousCache[i] << endl; cout << "to: " << nelemRequested << " but got instead: " << nelemRequestedCheck << endl; } } } //if size_t //start time double timeElapsed=0; double timeElapsed2=0; double timeElapsedBase=0; using namespace boost::posix_time; ptime timeStart(microsec_clock::local_time()); for (size_t i=0; i< handleMatch.size(); ++i) { valGetA[0]=0; status=Instant::getCache(handleMatch[i], dbrType, valGetA); valGet[i]=valGetA[0]; if (status !=ICAFE_NORMAL) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cstat.report(status); } ///valGet[i]=valGetA[0][i]; if (dbrType==DBR_CHAR) {valGet[i] = (unsigned short) valGet[i];} if(printFlag) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Current Cached Value = " << valGet[i] << endl; cout << "Lower/Upper Target Values = " << valSetLower[i] << " and " << valSetUpper[i] << endl; } } //for size_t ptime timeEnd(microsec_clock::local_time()); time_duration duration(timeEnd-timeStart); timeElapsed= (double) duration.total_microseconds()/1000000.0; for (size_t i=0; i< handleMatch.size(); ++i) { while ( (valGet[i]>valSetUpper[i] || valGet[i]1 && status==ICAFE_NORMAL) { for (size_t ij=0; ij< handleMatch.size(); ++ij) { status=Instant::getCache(handleMatch[ij], dbrType, valGetA); valGet[ij]=valGetA[0]; if (valGet[ij]>valSetUpper[ij] || valGet[ij]1) { nelemPreviousCheck= helper.setNelemToRetrieveFromCache(handleMatch[i],nelemPreviousCache[i]); if (nelemPreviousCheck != nelemPreviousCache[i]) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Internal CAFE FUNNY: Wanted to re-set the no. elements from: " << nelemRequested << endl; cout << "to the previous: " << nelemPreviousCache[i] << " but got instead: " << nelemPreviousCheck << endl; } } if (nMonitors[i]==0 && statMonitor[i]==ICAFE_NORMAL) { cout << "STOPPING MONITOR WITH ID =" << monitorID[i] << endl; int statm; statm=connect.monitorStop(handleMatch[i], monitorID[i]); if(status==ICAFE_NORMAL){status=statm;} } } //for return status; #undef __METHOD__ } #endif // instant.cpp