/// /// \file cafeGroup.cpp /// /// \author Jan Chrin, PSI /// \date January 2016 /// \version CAFE 1.0.0 /// #include using namespace std; //// Groups /** * \brief Fills the PVGroup object indentified by the groupHandle from memory.\n * Does NOT do a "get". Method used to fill the PVGroup class with meta-data. * \param _groupHandle input: handle to the group object * \param pvgroup output: data pertaining to the object * \return statusGroup */ int CAFE::groupFetch(const unsigned int _groupHandle, PVGroup &pvgroup) { #define __METHOD__ "groupFetch( _groupHandle, &pvgroup)" string s = handleHelper.getGroupNameFromGroupHandle(_groupHandle); if (s!="") { bool groupExists=false; for (unsigned short i = 0; i < PVGroupV.size(); ++i) { if (strcmp(PVGroupV[i].name, s.c_str()) == 0) { pvgroup = PVGroupV[i]; pvgroup.groupHandle=_groupHandle; groupExists=true; break; } } if (!groupExists) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_UNKNOWN_GROUP); return ECAFE_UNKNOWN_GROUP; } } else { return ECAFE_UNKNOWN_GROUP; } return ICAFE_NORMAL; #undef __METHOD__ }; /** * \brief Fills the PVGroup object indentified by the groupHandle from memory.\n * Method used to fill the PVGroup class both with meta-data and actual data * (from hash table) * \param _groupHandle input: handle to the group object * \param pvgroup output: data pertaining to the object * \return statusGroup */ int CAFE::groupAttach(const unsigned int _groupHandle, PVGroup &pvgroup) { #define __METHOD__ "groupAttach(_groupHandle, &pvgroup)" string s = handleHelper.getGroupNameFromGroupHandle(_groupHandle); unsigned int iIdx; if (s!="") { bool groupExists=false; for (unsigned short i = 0; i < PVGroupV.size(); ++i) { if (strcmp(PVGroupV[i].name, s.c_str()) == 0) { pvgroup = PVGroupV[i]; iIdx=i; groupExists=true; break; } } if (!groupExists) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_UNKNOWN_GROUP); return ECAFE_UNKNOWN_GROUP; } } else { return ECAFE_UNKNOWN_GROUP; } //Fill group from current data in hash table: pvgroup.statusGroup=ICAFE_NORMAL; cafeGroup_set_by_groupHandle & groupHandle_index = gs.get (); cafeGroup_set_by_groupHandle::iterator it_groupHandle; it_groupHandle = groupHandle_index.find(_groupHandle); if (it_groupHandle != groupHandle_index.end()) { unsigned int nGroupMember = (*it_groupHandle).getNMember(); if (pvgroup.npv != (*it_groupHandle).getNMember()) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "A MISMATCH IN THE NUMBER OF GROUP MEMBERS DETECTED " << endl; cout << "CLIENT (pvgroup.npv) CLAIMS " << pvgroup.npv << " CONDUITGROUP OBJECT CLAIMS " << (*it_groupHandle).getNMember() << endl; nGroupMember = min(pvgroup.npv,(*it_groupHandle).getNMember()); cout << "TAKING SMALLER OF THE TWO NUMBERS " << endl; } cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; for (unsigned int iMember = 0; iMember < nGroupMember; ++iMember) { bool hf=false; //reset pvgroup.pvdata[iMember].alarmStatus =-1; pvgroup.pvdata[iMember].alarmSeverity =-1; pvgroup.pvdata[iMember].ts.secPastEpoch=0; pvgroup.pvdata[iMember].ts.nsec=0; pvgroup.pvdata[iMember].hasAlarm=true; pvgroup.pvdata[iMember].hasTS=true; pvgroup.pvdata[iMember].rule=true; pvgroup.pvdata[iMember].status=ICAFE_NORMAL; it_handle = handle_index.find((*it_groupHandle).mHandle[iMember]); if (it_handle != handle_index.end()) { hf=true; } if (!hf) { pvgroup.pvdata[iMember].status=ECAFE_INVALID_HANDLE; if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); cout << "Invalid handle = " << (*it_groupHandle).mHandle[iMember] << " for groupMember [" << iMember << "] " << endl; pvgroup.statusGroup=ECAFE_INVALID_HANDLE; continue; } if (!(*it_handle).getChannelRegalia().getConnectFlag()) { if (pvgroup.statusGroup==ICAFE_NORMAL) { pvgroup.statusGroup=(*it_handle).getChannelRegalia().getCafeConnectionState(); } } //this sets size and nelem to 1 if not connected //unsigned int a= pvgroup.pvdata[iMember].setNelem( (*it_handle).getChannelRegalia().getNelem() ); //set Device, Attribute for handle ChannelDeviceAttribute channelDeviceAttribute; channelDeviceAttribute.init((*it_handle).pv, deviceAttributeDeliminator); if(MUTEX) { cafeMutex.lock(); } handle_index.modify(it_handle, change_channelDeviceAttribute( channelDeviceAttribute)); if(MUTEX) { cafeMutex.unlock(); } //Above lines replace need for handleHelper // handleHelper.setChannelDeviceAttribute(deviceAttributeDeliminator); (*it_handle).getPVDataHolder(pvgroup.pvdata[iMember]); } //for PVGroupV[iIdx]=pvgroup; pvgroup.groupHandle=_groupHandle; return pvgroup.statusGroup; } else { return ECAFE_INVALID_GROUP_HANDLE; } #undef __METHOD__ }; /** * \brief Fills the PVGroup object indentified by pvgroup.groupHandle \n * \param pvgroup input/output: data pertaining to the object * \return statusGroup */ int CAFE::groupSet(PVGroup &pvgroup) { #define __METHOD__ "groupSet(&pvgroup)" return CAFE::groupSet(pvgroup.groupHandle, pvgroup); #undef __METHOD__ }; /** * \brief Fills the PVGroup object indentified by the groupHandle \n * \param _groupHandle input: handle to the group object * \param pvgroup input/output: data pertaining to the object * \return statusGroup */ int CAFE::groupSet(const unsigned int _groupHandle, PVGroup &pvgroup) { #define __METHOD__ "groupSet( _groupHandle, &pvgroup)" if (pvgroup.npv==0) { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_EMPTY_GROUP); return ECAFE_EMPTY_GROUP; } else if (pvgroup.groupHandle!=_groupHandle) { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Input groupHandle " << _groupHandle << " does not match that within pvgroup " << pvgroup.groupHandle << endl; cout << "groupSet operation NOT attempted. Client clarification required! " << endl; cafeStatus.report(ECAFE_PVGROUP_GROUPHANDLE_MISMATCH); return ECAFE_PVGROUP_GROUPHANDLE_MISMATCH; } int gStatus=ICAFE_NORMAL; cafeGroup_set_by_groupHandle & groupHandle_index = gs.get (); cafeGroup_set_by_groupHandle::iterator it_groupHandle; it_groupHandle = groupHandle_index.find(_groupHandle); if (it_groupHandle != groupHandle_index.end()) { unsigned int nGroupMember = (*it_groupHandle).getNMember(); if (pvgroup.npv != (*it_groupHandle).getNMember()) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "A MISMATCH IN THE NUMBER OF GROUP MEMBERS DETECTED " << endl; cout << "CLIENT (pvgroup.npv) CLAIMS " << pvgroup.npv << " CONDUITGROUP OBJECT CLAIMS " << (*it_groupHandle).getNMember() << endl; nGroupMember = min(pvgroup.npv,(*it_groupHandle).getNMember()); cout << "TAKING SMALLER OF THE TWO NUMBERS " << endl; } cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; bool * nelemPreviousFlag = new bool [nGroupMember]; unsigned int * nelemPrevious = new unsigned int [nGroupMember]; for (unsigned int iMember = 0; iMember < nGroupMember; ++iMember) { bool hf=false; //reset pvgroup.pvdata[iMember].alarmStatus=-1; pvgroup.pvdata[iMember].alarmSeverity=-1; pvgroup.pvdata[iMember].ts.secPastEpoch=0; pvgroup.pvdata[iMember].ts.nsec=0; pvgroup.pvdata[iMember].status=ICAFE_NORMAL; it_handle = handle_index.find((*it_groupHandle).mHandle[iMember]); if (it_handle != handle_index.end()) { hf=true; if (pvgroup.pvdata[iMember].getRule() != (*it_groupHandle).getRule(iMember)) { if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_rule(pvgroup.pvdata[iMember].rule, iMember)); if(MUTEX) { cafeMutex.unlock(); } } if (!pvgroup.pvdata[iMember].getRule() ) { pvgroup.pvdata[iMember].status=ICAFE_RULE_FALSE; } if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } } if (!hf) { nelemPrevious[iMember]=0; nelemPreviousFlag[iMember]=false; pvgroup.pvdata[iMember].status=ECAFE_INVALID_HANDLE; if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); cout << "Invalid handle = " << (*it_groupHandle).mHandle[iMember] << " for groupMember [" << iMember << "] " << endl; continue; } unsigned int handle=(*it_groupHandle).mHandle[iMember]; nelemPrevious[iMember]=handleHelper.getNelemClient(handle); nelemPreviousFlag[iMember]=false; //Find Native DataType if ( (pvgroup.pvdata[iMember].status=cafeGranules.channelVerifyPut(handle, pvgroup.pvdata[iMember].dataType)) != ICAFE_NORMAL) { if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "CHANNEL: " << pvgroup.pvdata[iMember].pv << endl; cafeStatus.report(pvgroup.pvdata[iMember].status); continue; } // Examine No of elements and set accordingly.... if (handleHelper.getNelemClient(handle) != pvgroup.pvdata[iMember].getNelem()) { nelemPreviousFlag[iMember]=true; handleHelper.setNelem(handle, pvgroup.pvdata[iMember].getNelem()); //cout << "INFO: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; //cout << "Changing handleHelper.getNelemClient(handle) to that given in pvgroup.pvdata[iMember].nelem " << endl; //cout << "i.e., To: " << pvgroup.pvdata[iMember].nelem << " From: " << handleHelper.getNelemClient(handle) << endl; } if ( (pvgroup.pvdata[iMember].status=cafeGranules.channelPreparePut(handle)) != ICAFE_NORMAL) { if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(pvgroup.pvdata[iMember].status); continue; } pvgroup.pvdata[iMember].dbrDataType= ((*it_handle).getChannelRequestMetaPrimitive().getDbrDataType()); switch ((*it_handle).getChannelRequestMetaPrimitive().getDbrDataType()) { case DBR_STRING: renderString.putString(handle, pvgroup.pvdata[iMember].val.get()); break; case DBR_SHORT: renderShort.put(handle, pvgroup.pvdata[iMember].val.get(), pvgroup.pvdata[iMember].dataType); break; case DBR_FLOAT: renderFloat.put(handle, pvgroup.pvdata[iMember].val.get(), pvgroup.pvdata[iMember].dataType); break; case DBR_ENUM: renderEnum.put(handle, pvgroup.pvdata[iMember].val.get(), pvgroup.pvdata[iMember].dataType); break; case DBR_CHAR: renderChar.put(handle, pvgroup.pvdata[iMember].val.get(), pvgroup.pvdata[iMember].dataType); break; case DBR_LONG: renderLong.put(handle, pvgroup.pvdata[iMember].val.get(), pvgroup.pvdata[iMember].dataType); break; case DBR_DOUBLE: renderDouble.put(handle, pvgroup.pvdata[iMember].val.get(), pvgroup.pvdata[iMember].dataType); break; default: cout << "ERROR: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_SWITCH_CASE); cout << "SWITCH STATMENT NOT MEANT FOR CAFE DATATYPE=" << pvgroup.pvdata[iMember].dataType < 0 ) { //if (ntries >= channelTimeoutPolicySGPut.getNtries() ) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; std::cout << "No of(additional) tries=" << ntries << std::endl; if (gStatus==ECAFE_TIMEOUT) { std::cout << "is the MAXIMUM allowed as configured through SGTimeoutPolicy! " << std::endl; std::cout << "SETTING SELF-GOVERNING TIMEOUT FOR SG PUT OPERATIONS FOR THIS CHANNEL TO FALSE" << std::endl; std::cout << "RESTORING TIMEOUT TO ORIGINAL SG PUT VALUE OF: " << originalTimeOut << " SECONDS " << std::endl; channelTimeoutPolicySGPut.setSelfGoverningTimeout(false); channelTimeoutPolicySGPut.setTimeout( originalTimeOut ); if(MUTEX) { cafeMutex.lock(); //lock } groupHandle_index.modify(it_groupHandle, change_channelTimeoutPolicySGPut(channelTimeoutPolicySGPut)); if(MUTEX) { cafeMutex.unlock(); //unlock } } else { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Changed SG PUT from intitial " << originalTimeOut << " to: " << (originalTimeOut + channelTimeoutPolicySGPut.getDeltaTimeout()*ntries) << " seconds after " << ntries << " sg_put calls " < &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::set(CAFE::getHandlesFromWithinGroupV(_groupHandle)[9],8.88); status=CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { cout << pvgroup.pvdata[iMember].getAsString(0) << " ts " << pvgroup.pvdata[iMember].ts.secPastEpoch << " " << pvgroup.pvdata[iMember].ts.nsec << " STATUS " << pvgroup.pvdata[iMember].status << " iMember" << iMember << endl; valV.push_back(pvgroup.pvdata[iMember].getAsString(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } if (pvgroup.statusGroup==ECA_TIMEOUT) { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECA_TIMEOUT); cout << "SG TIMEOUT OCCURRED. REVERTING TO ASYNCHRNOUS GET" << endl; return CAFE::getScalars(CAFE::getHandlesFromWithinGroupV(_groupHandle), valV, statusV); } else { return pvgroup.statusGroup; } #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of double values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsDouble(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of float values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsFloat(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of short values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsShort(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of long values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsLong(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of long long values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsLongLong(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of unsigned short values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsUShort(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of unsigned char values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsUChar(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param valV output: vector of char values * \param statusV output: vector of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::vector &valV, std::vector &statusV) { #define __METHOD__ "groupGetScalar( _groupHandle, vector &valV, vector &statusV)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); valV.reserve(pvgroup.npv); statusV.reserve(pvgroup.npv); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { valV.push_back(pvgroup.pvdata[iMember].getAsChar(0)); statusV.push_back(pvgroup.pvdata[iMember].status); } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of string values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, std::string * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, string * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsString(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of double values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, double * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, double * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsDouble(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of float values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, float * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, float * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsFloat(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of short values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, short * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, short * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsShort(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of long values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, long * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, long * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsLong(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of long long values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, long long * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, long long * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsLongLong(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of unsigned short values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, unsigned short * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, unsigned short * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsUShort(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of unsigned char values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, unsigned char * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, unsigned char * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsUChar(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } //Asynchronous get //get() //waitForBundleEvents //getCache return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Retrieves scalar value from the PVGroup object indentified by the group handle \n * \param _groupHandle input: handle to the group object * \param val output: array of char values * \param statusArray output: array of int values reporting the status * \return statusGroup */ int CAFE::groupGetScalar(const unsigned int _groupHandle, char * val, int * statusArray) { #define __METHOD__ "groupGetScalar( _groupHandle, char * val, int * statusArray)" PVGroup pvgroup; CAFE::groupAttach(_groupHandle, pvgroup); pvgroup.setHasAlarm(false); pvgroup.setHasTS(false); CAFE::groupGet(_groupHandle, pvgroup); for (unsigned int iMember = 0; iMember < pvgroup.npv; ++iMember) { val[iMember]=pvgroup.pvdata[iMember].getAsChar(0); statusArray[iMember]=pvgroup.pvdata[iMember].status; } return pvgroup.statusGroup; #undef __METHOD__ } /** * * \brief Fills the PVGroup object indentified by the pvgroup.groupHandle \n * \param pvgroup input/output: data pertaining to the object * \return statusGroup */ int CAFE::groupGet(PVGroup &pvgroup) { #define __METHOD__ "groupGet(&pvgroup)" return CAFE::groupGet(pvgroup.groupHandle, pvgroup); #undef __METHOD__ } /** * \brief Fills the PVGroup object indentified by the groupHandle \n * \param _groupHandle input: handle to the group object * \param pvgroup output: data pertaining to the object * \return statusGroup */ int CAFE::groupGet(const unsigned int _groupHandle, PVGroup &pvgroup) { #define __METHOD__ "groupGet( _groupHandle, &pvgroup)" int gStatus=ICAFE_NORMAL; if (pvgroup.npv==0 || pvgroup.groupHandle==0) { gStatus=groupAttach(_groupHandle, pvgroup); if (gStatus != ICAFE_NORMAL) { return gStatus; } }; if (pvgroup.groupHandle != _groupHandle) { return ECAFE_PVGROUP_GROUPHANDLE_MISMATCH; } cafeGroup_set_by_groupHandle & groupHandle_index = gs.get (); cafeGroup_set_by_groupHandle::iterator it_groupHandle; it_groupHandle = groupHandle_index.find(_groupHandle); if (it_groupHandle != groupHandle_index.end()) { unsigned int nGroupMember = (*it_groupHandle).getNMember(); if (pvgroup.npv != (*it_groupHandle).getNMember()) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "A MISMATCH IN THE NUMBER OF GROUP MEMBERS DETECTED " << endl; cout << "CLIENT (pvgroup.npv) CLAIMS " << pvgroup.npv << " CONDUITGROUP OBJECT CLAIMS " << (*it_groupHandle).getNMember() << endl; nGroupMember = min(pvgroup.npv,(*it_groupHandle).getNMember()); cout << "TAKING SMALLER OF THE TWO NUMBERS " << endl; } cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; for (unsigned int iMember = 0; iMember < nGroupMember; ++iMember) { bool hf=false; //reset pvgroup.pvdata[iMember].alarmStatus=-1; pvgroup.pvdata[iMember].alarmSeverity=-1; pvgroup.pvdata[iMember].ts.secPastEpoch=0; pvgroup.pvdata[iMember].ts.nsec=0; pvgroup.pvdata[iMember].status=ICAFE_NORMAL; it_handle = handle_index.find((*it_groupHandle).mHandle[iMember]); if (it_handle != handle_index.end()) { hf=true; if (pvgroup.pvdata[iMember].getRule() != (*it_groupHandle).getRule(iMember)) { if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_rule(pvgroup.pvdata[iMember].rule, iMember)); if(MUTEX) { cafeMutex.unlock(); } } if (!pvgroup.pvdata[iMember].getRule() ) { pvgroup.pvdata[iMember].status=ICAFE_RULE_FALSE; } if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } } if (!hf) { pvgroup.pvdata[iMember].status=ECAFE_INVALID_HANDLE; if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); cout << "Invalid handle = " << (*it_groupHandle).mHandle[iMember] << " for groupMember [" << iMember << "] " << endl; continue; } unsigned int handle=(*it_groupHandle).mHandle[iMember]; //May happen that channel has just connected and native datatype not yet entered CAFE_DATATYPE cdt = pvgroup.pvdata[iMember].dataType; //Check groupDataType if (pvgroup.pvdata[iMember].dataTypeCAFE_DOUBLE) { cdt=CAFE_STRING; } //Let us take a look at hasAlarm and hasTS flags to determine if these are retrieved from SC chtype _chtype= cdt; if (!pvgroup.pvdata[iMember].hasAlarm && !pvgroup.pvdata[iMember].hasTS) { handleHelper.setCafeDbrType(handle, CAFENUM::DBR_PRIMITIVE); } else if (pvgroup.pvdata[iMember].hasAlarm && !pvgroup.pvdata[iMember].hasTS) { _chtype=dbf_type_to_DBR_STS (cdt); handleHelper.setCafeDbrType(handle, CAFENUM::DBR_STS) ; } else if (pvgroup.pvdata[iMember].hasTS) { _chtype=dbf_type_to_DBR_TIME (cdt); handleHelper.setCafeDbrType(handle, CAFENUM::DBR_TIME) ; } //Always Return to Native DataType for now if ( (pvgroup.pvdata[iMember].status=cafeGranules.channelVerifyGet(handle, _chtype)) != ICAFE_NORMAL) { //dbf_type_to_DBR_TIME (cdt))) != ICAFE_NORMAL) { if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } //May not be connected - wish to report this here cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "CHANNEL: " << pvgroup.pvdata[iMember].pv << endl; cafeStatus.report(pvgroup.pvdata[iMember].status); continue; } // Examine the No of elements and set accordingly.... if ( handleHelper.getNelemClient(handle) != pvgroup.pvdata[iMember].getNelem()) { cout << "INFO: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Changing handleHelper.getNelemClient(handle) to that given in pvgroup.pvdata[iMember].nelem" << endl; cout << "i.e., From: " << handleHelper.getNelemClient(handle) << " To: " << pvgroup.pvdata[iMember].nelem << endl; handleHelper.setNelem(handle, pvgroup.pvdata[iMember].getNelem()); //Change made back 12 September 2019 /* //Change made 17 March 2017 cout << "INFO: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cout << "Changing pvgroup.pvdata[iMember].nelem to that given in handleHelper.getNelemClient(handle)" << endl; cout << "i.e., From: " << pvgroup.pvdata[iMember].nelem << " To: " << handleHelper.getNelemClient(handle) << endl; pvgroup.pvdata[iMember].nelem=handleHelper.getNelemClient(handle); */ } if ( (pvgroup.pvdata[iMember].status=cafeGranules.channelPrepareGet(handle)) != ICAFE_NORMAL) { if(MUTEX) { cafeMutex.lock(); } groupHandle_index.modify(it_groupHandle, change_sg_status(pvgroup.pvdata[iMember].status, iMember)); if(MUTEX) { cafeMutex.unlock(); } cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(pvgroup.pvdata[iMember].status); continue; } } //for gStatus=(*it_groupHandle).get(); channelTimeoutPolicySGGet = (*it_groupHandle).getChannelTimeoutPolicySGGet(); //this returns normal even if a channel is not connected if (gStatus!=ECA_NORMAL && channelTimeoutPolicySGGet.getSelfGoverningTimeout()) { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(gStatus); if (gStatus == ECA_TIMEOUT) { cout << "ENABLING AUTO- CORRECTIVE PROCEDURE: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; } } unsigned short ntries=0; double originalTimeOut=channelTimeoutPolicySGGet.getTimeout(); //Withdraw this test for now; not required //if (ca_sg_test((*it_groupHandle).getGroupID()) == ECA_IOINPROGRESS ) { // cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; // cafeStatus.report(ECA_IOINPROGRESS); //} //Withdraw this test for now; not required //while ( (ca_sg_test((*it_groupHandle).getGroupID()) == ECA_IOINPROGRESS // || gStatus == ECA_TIMEOUT) && channelTimeoutPolicySGGet.getSelfGoverningTimeout() // && ntries0) { //if (ntries >= channelTimeoutPolicySGGet.getNtries() ) { cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; std::cout << "No of(additional) tries=" << ntries << std::endl; if (gStatus==ECAFE_TIMEOUT) { std::cout << "is the MAXIMUM allowed as configured through SGTimeoutPolicy! " << std::endl; std::cout << "SETTING SELF-GOVERNING TIMEOUT FOR SG GET OPERATIONS FOR THIS CHANNEL TO FALSE" << std::endl; std::cout << "RESTORING TIMEOUT TO ORIGINAL SG GET VALUE OF: " << originalTimeOut << " SECONDS " << std::endl; channelTimeoutPolicySGGet.setSelfGoverningTimeout(false); channelTimeoutPolicySGGet.setTimeout( originalTimeOut ); if(MUTEX) { cafeMutex.lock(); //lock } groupHandle_index.modify(it_groupHandle, change_channelTimeoutPolicySGGet(channelTimeoutPolicySGGet)); if(MUTEX) { cafeMutex.unlock(); //unlock } } else { cout << "Changed SG GET from intitial " << originalTimeOut << " to: " << (originalTimeOut + channelTimeoutPolicySGGet.getDeltaTimeout()*ntries) << " seconds" << endl; } } //if //Withdraw this test for now; not required //if (ca_sg_test((*it_groupHandle).getGroupID()) == ECA_IOINPROGRESS) { // ca_sg_reset((*it_groupHandle).getGroupID()); // cout << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; // std::cout << " No. of ca_sg_test(gid) INSTIGATED: " << ntries+1 << std::endl; // std::cout // << " ca_sg_reset(gid) HAS BEEN FORCED SO THAT ca_sg_test() returns ECA_IODONE" // < &statusV, std::vector &mpV) { #define __METHOD__ "groupMonitorStart(groupHandle, &statusV, &mpV)" // open groupHandle cafeGroup_set_by_groupHandle & groupHandle_index = gs.get (); cafeGroup_set_by_groupHandle::iterator it_groupHandle; it_groupHandle = groupHandle_index.find(groupHandle); if (it_groupHandle != groupHandle_index.end()) { unsigned int nGroupMember = (*it_groupHandle).getNMember(); vector handleV; handleV.reserve(nGroupMember); cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; // fill vector of member handles for (unsigned int iMember = 0; iMember < nGroupMember; ++iMember) { it_handle = handle_index.find((*it_groupHandle).mHandle[iMember]); if (it_handle != handle_index.end()) { handleV.push_back((*it_groupHandle).mHandle[iMember]); } else { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); cout << "Invalid handle = " << (*it_groupHandle).mHandle[iMember] << " for groupMember [" << iMember << "] " << endl; continue; } } // issue monitorStart command return monitorStart(handleV, statusV, mpV); } else { return ECAFE_INVALID_GROUP_HANDLE; } #undef __METHOD__ } /** * \brief Starts a monitor on all PVs within the PVGroup object indentified by the groupHandle \n * \param groupHandle input: handle to the group object * \param statusV output: status of individual monitors * \param monitorIDV output: vector of monitor ID (unsigned int) * \return ECAFE_NORMAL if all OK else first error encountered */ int CAFE::groupMonitorStart(const unsigned int groupHandle, std::vector &statusV, std::vector &monitorIDV) { #define __METHOD__ "groupMonitorStart(groupHandle, &statusV, &monitorIDV)" // open groupHandle cafeGroup_set_by_groupHandle & groupHandle_index = gs.get (); cafeGroup_set_by_groupHandle::iterator it_groupHandle; it_groupHandle = groupHandle_index.find(groupHandle); if (it_groupHandle != groupHandle_index.end()) { unsigned int nGroupMember = (*it_groupHandle).getNMember(); vector handleV; handleV.reserve(nGroupMember); cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; // fill vector of member handles for (unsigned int iMember = 0; iMember < nGroupMember; ++iMember) { it_handle = handle_index.find((*it_groupHandle).mHandle[iMember]); if (it_handle != handle_index.end()) { handleV.push_back((*it_groupHandle).mHandle[iMember]); } else { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); cout << "Invalid handle = " << (*it_groupHandle).mHandle[iMember] << " for groupMember [" << iMember << "] " << endl; continue; } } // issue monitorStart command return monitorStart(handleV, statusV, monitorIDV); } else { return ECAFE_INVALID_GROUP_HANDLE; } #undef __METHOD__ } /** * \brief Stops a monitor on all PVs within the PVGroup object indentified by the groupHandle \n * \param groupHandle input: handle to the group object * \param statusV output: status of individual monitor stop operations * \return ECAFE_NORMAL if all OK else first error encountered */ int CAFE::groupMonitorStop (const unsigned int groupHandle, std::vector &statusV) { #define __METHOD__ "groupMonitorStop(groupHandle, &statusV)" // open groupHandle cafeGroup_set_by_groupHandle & groupHandle_index = gs.get (); cafeGroup_set_by_groupHandle::iterator it_groupHandle; it_groupHandle = groupHandle_index.find(groupHandle); if (it_groupHandle != groupHandle_index.end()) { unsigned int nGroupMember = (*it_groupHandle).getNMember(); vector handleV; handleV.reserve(nGroupMember); cafeConduit_set_by_handle & handle_index = cs.get (); cafeConduit_set_by_handle::iterator it_handle; // fill vector of member handles for (unsigned int iMember = 0; iMember < nGroupMember; ++iMember) { it_handle = handle_index.find((*it_groupHandle).mHandle[iMember]); if (it_handle != handle_index.end()) { handleV.push_back((*it_groupHandle).mHandle[iMember]); } else { cout << "WARNING: " << __FILE__ << "//" << __LINE__ << "//" << __METHOD__ << endl; cafeStatus.report(ECAFE_INVALID_HANDLE); cout << "Invalid handle = " << (*it_groupHandle).mHandle[iMember] << " for groupMember [" << iMember << "] " << endl; continue; } } // issue monitorStart command return monitorStop(handleV, statusV); } else { return ECAFE_INVALID_GROUP_HANDLE; } #undef __METHOD__ }