added enum string table cache to PV class

This commit is contained in:
Jeff Hill
1999-10-28 18:53:56 +00:00
parent 8ac6bec3d7
commit a461bb8535
4 changed files with 188 additions and 22 deletions

View File

@@ -344,6 +344,8 @@ public:
void postAccessRightsEvent ();
const vector<string> enumStringTable () const;
//
// virtual functions
//
@@ -444,7 +446,10 @@ public:
caStatus bestDBRType (unsigned &dbrType);
epicsShareFunc virtual casResType resourceType () const;
const vector<string> enumStringTable () const;
void updateEnumStringTable (unsigned nativeType);
//
// virtual functions in the public interface class
//
@@ -465,6 +470,7 @@ public:
private:
tsDLList<casPVListChan> chanList;
vector<string> enumStrTbl;
caServerI *pCAS;
unsigned nMonAttached;
unsigned nIOAttached;
@@ -472,7 +478,6 @@ private:
inline void lock () const;
inline void unlock () const;
epicsShareFunc virtual void destroy (); // casPVI destructor noop
};

View File

@@ -28,6 +28,7 @@
*
*/
#include "gddAppTable.h" // EPICS application type table
#include "server.h"
#include "casPVIIL.h" // casPVI inline func
@@ -104,7 +105,6 @@ void casPVI::destroy ()
//
caStatus casPVI::attachToServer (caServerI &cas)
{
if (this->pCAS) {
//
// currently we enforce that the PV can be attached to only
@@ -115,6 +115,7 @@ caStatus casPVI::attachToServer (caServerI &cas)
}
}
else {
//
// install the PV into the server
//
@@ -124,6 +125,129 @@ caStatus casPVI::attachToServer (caServerI &cas)
return S_cas_success;
}
//
// casPVI::updateEnumStringTable ()
//
// fetch string conversion table so that we can perform proper conversion
// of enumerated PVs to strings during reads
//
// what a API complexity nightmare this GDD is
//
void casPVI::updateEnumStringTable (unsigned nativeType)
{
static const aitUint32 stringTableTypeStaticInit = 0xffffffff;
static aitUint32 stringTableType = stringTableTypeStaticInit;
caStatus status;
gdd *pTmp;
//
// reload the enum string table each time that the
// PV is attached to the server
//
this->enumStrTbl.clear ();
//
// empty string table for non-enumerated PVs
//
if (nativeType!=aitEnumEnum16) {
this->enumStrTbl.clear ();
return;
}
//
// lazy init
//
if (stringTableType==stringTableTypeStaticInit) {
stringTableType = gddApplicationTypeTable::app_table.registerApplicationType ("enums");
}
//
// create a gdd with the "enum string table" application type
//
pTmp = new gddScalar (stringTableType);
if (pTmp==NULL) {
errMessage (S_cas_noMemory, "unable to read application type \"enums\" string conversion table for enumerated PV");
return;
}
//
// create a false context which is guaranteed to cause
// any asynch IO to be ignored
//
casCtx ctx;
//
// read the enum string table
//
status = this->read (ctx, *pTmp);
if (status == S_casApp_asyncCompletion || status == S_casApp_postponeAsyncIO) {
pTmp->unreference ();
errMessage (status, " sorry, no support in server library for asynchronous completion of \"enums\" string conversion table for enumerated PV");
errMessage (status, " please fetch \"enums\" string conversion table into cache during asychronous PV attach IO completion");
return;
}
else if (status) {
pTmp->unreference ();
errMessage (status, "unable to read application type \"enums\" string conversion table for enumerated PV");
return;
}
if (pTmp->isContainer()) {
errMessage (S_cas_badType, "application type \"enums\" string conversion table for enumerated PV was a container (expected vector of strings)");
pTmp->unreference ();
return;
}
if (pTmp->dimension()==0) {
if (pTmp->primitiveType()==aitEnumString) {
aitString *pStr = (aitString *) pTmp->dataVoid ();
this->enumStrTbl[0].assign (pStr->string());
}
else if (pTmp->primitiveType()==aitEnumFixedString) {
aitFixedString *pStr = (aitFixedString *) pTmp->dataVoid ();
this->enumStrTbl[0].assign (pStr->fixed_string);
}
else {
errMessage (S_cas_badType, "application type \"enums\" string conversion table for enumerated PV isnt a string type?");
}
}
else if (pTmp->dimension()==1) {
gddStatus status;
aitIndex index, first, count;
status = pTmp->getBound (0, first, count);
assert (status == 0);
//
// preallocate the correct amount
//
this->enumStrTbl.reserve (count);
if (pTmp->primitiveType()==aitEnumString) {
aitString *pStr = (aitString *) pTmp->dataVoid ();
for (index = 0; index<count; index++) {
this->enumStrTbl[index].assign (pStr[index].string());
}
}
else if (pTmp->primitiveType()==aitEnumFixedString) {
aitFixedString *pStr = (aitFixedString *) pTmp->dataVoid ();
for (index = 0; index<count; index++) {
this->enumStrTbl[index].assign (pStr[index].fixed_string);
}
}
else {
errMessage (S_cas_badType, "application type \"enums\" string conversion table for enumerated PV isnt a string type?");
}
}
else {
errMessage (S_cas_badType, "application type \"enums\" string conversion table for enumerated PV was multi-dimensional (expected vector of strings)");
}
pTmp->unreference ();
return;
}
//
// casPVI::registerEvent()
//

View File

@@ -198,6 +198,14 @@ inline aitIndex casPVI::nativeCount ()
return this->maxBound(0u);
}
//
// casPVI::enumStringTable ()
//
inline const vector<string> casPVI::enumStringTable () const
{
return this->enumStrTbl;
}
#endif // casPVIIL_h

View File

@@ -109,6 +109,31 @@ casStrmClient::~casStrmClient()
this->unlock();
}
//
// casStrmClient::uknownMessageAction()
//
caStatus casStrmClient::uknownMessageAction ()
{
const caHdr *mp = this->ctx.getMsg();
caStatus status;
ca_printf ("CAS: bad request code from virtual circuit=%u\n", mp->m_cmmd);
this->dumpMsg (mp, this->ctx.getData());
/*
* most clients dont recover from this
*/
status = this->sendErr (mp, ECA_INTERNAL, "Invalid Request Code");
if (status) {
return status;
}
/*
* returning S_cas_internal here disconnects
* the client with the bad message
*/
return S_cas_internal;
}
//
// casStrmClient::verifyRequest()
@@ -171,7 +196,6 @@ void casStrmClient::show (unsigned level) const
this->outBuf::show(level);
}
/*
* casStrmClient::readAction()
*/
@@ -215,7 +239,7 @@ caStatus casStrmClient::readAction ()
pChan->getPVI().addItemToIOBLockedList(*this);
}
else {
status = this->sendErrWithEpicsStatus(mp, status, ECA_GETFAIL);
status = this->sendErrWithEpicsStatus (mp, status, ECA_GETFAIL);
}
return status;
@@ -257,7 +281,7 @@ caStatus casStrmClient::readResponse (casChannelI *pChan, const caHdr &msg,
// convert gdd to db_access type
// (places the data in network format)
//
mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr((reply+1), msg.m_count, desc);
mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr((reply+1), msg.m_count, desc, pChan->enumStringTable());
if (mapDBRStatus<0) {
desc.dump();
errPrintf (S_cas_badBounds, __FILE__, __LINE__, "- get with PV=%s type=%u count=%u",
@@ -419,7 +443,7 @@ caStatus casStrmClient::readNotifyResponseECA_XXX (casChannelI *pChan,
// convert gdd to db_access type
// (places the data in network format)
//
mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr((reply+1), msg.m_count, *pDesc);
mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr((reply+1), msg.m_count, *pDesc, pChan->enumStringTable());
if (mapDBRStatus<0) {
pDesc->dump();
errPrintf (S_cas_badBounds, __FILE__, __LINE__, "- get notify with PV=%s type=%u count=%u",
@@ -555,7 +579,7 @@ caStatus casStrmClient::monitorResponse(casChannelI &chan, const caHdr &msg,
// there appears to be no success/fail
// status from this routine
//
gddMapDbr[msg.m_dataType].conv_dbr ((pReply+1), msg.m_count, *pDBRDD);
gddMapDbr[msg.m_dataType].conv_dbr ((pReply+1), msg.m_count, *pDBRDD, chan.enumStringTable());
#ifdef CONVERSION_REQUIRED
/* use type as index into conversion jumptable */
@@ -980,7 +1004,7 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur
casChannel *pChan;
casChannelI *pChanI;
caHdr *claim_reply;
unsigned dbrType;
unsigned nativeType;
bufSizeT nBytes;
caStatus status;
@@ -998,6 +1022,21 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur
return this->channelCreateFailed (&hdr, S_casApp_pvNotFound);
}
//
// fetch the native type
//
status = pPV->bestDBRType(nativeType);
if (status) {
errMessage(status, "best external dbr type fetch failed");
return this->channelCreateFailed (&hdr, status);
}
//
// fetch string conversion table so that we can perform proper conversion
// of enumerated PVs to strings during reads
//
pPV->updateEnumStringTable (nativeType);
//
// attach the PV to this server
//
@@ -1046,14 +1085,6 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur
return this->channelCreateFailed(&hdr, status);
}
status = pPV->bestDBRType(dbrType);
if (status) {
this->outBuf::popCtx (outctx);
errMessage(status, "best external dbr type fetch failed");
pChanI->destroyNoClientNotify();
return this->channelCreateFailed(&hdr, status);
}
//
// NOTE:
// We are allocated enough space for both the claim
@@ -1069,7 +1100,7 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur
*claim_reply = nill_msg;
claim_reply->m_cmmd = CA_PROTO_CLAIM_CIU;
claim_reply->m_dataType = dbrType;
claim_reply->m_dataType = nativeType;
claim_reply->m_count = pPV->nativeCount();
claim_reply->m_cid = hdr.m_cid;
claim_reply->m_available = pChanI->getSID();
@@ -1752,14 +1783,13 @@ caStatus casStrmClient::writeArrayData()
return status;
}
//
// casStrmClient::read()
//
caStatus casStrmClient::read(smartGDDPointer &pDescRet)
{
const caHdr *pHdr = this->ctx.getMsg();
caStatus status;
const caHdr *pHdr = this->ctx.getMsg();
caStatus status;
pDescRet = NULL;
status = createDBRDD (pHdr->m_dataType, pHdr->m_count, pDescRet);
@@ -1955,7 +1985,6 @@ caStatus createDBRDD (unsigned dbrType, aitIndex dbrCount, smartGDDPointer &pDes
}
//
// casStrmClient::userName()
//