use destroyInProgress flag now functional nativeCount()
This commit is contained in:
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.7 1996/11/02 00:54:23 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.6 1996/09/16 18:24:05 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -56,6 +59,13 @@
|
||||
|
||||
#include "dbMapper.h"
|
||||
|
||||
//
|
||||
// casPVI::getCAS()
|
||||
//
|
||||
inline caServerI &casPVI::getCAS()
|
||||
{
|
||||
return this->cas;
|
||||
}
|
||||
|
||||
//
|
||||
// casPVI::interfaceObjectPointer()
|
||||
@@ -175,7 +185,7 @@ inline void casPVI::deleteSignal()
|
||||
//
|
||||
localCASRef.osiLock();
|
||||
|
||||
if (this->chanList.count()==0u) {
|
||||
if (this->chanList.count()==0u && !this->destroyInProgress) {
|
||||
(*this)->destroy();
|
||||
//
|
||||
// !! dont access self after destroy !!
|
||||
@@ -230,6 +240,17 @@ inline void casPVI::postEvent (const casEventMask &select, gdd &event)
|
||||
this->unlock();
|
||||
}
|
||||
|
||||
//
|
||||
// CA only does 1D arrays for now
|
||||
//
|
||||
inline aitIndex casPVI::nativeCount()
|
||||
{
|
||||
if ((*this)->maxDimension()==0u) {
|
||||
return 1u; // scaler
|
||||
}
|
||||
return (*this)->maxBound(0u);
|
||||
}
|
||||
|
||||
#endif // casPVIIL_h
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <server.h>
|
||||
#include <casPVIIL.h>
|
||||
|
||||
//
|
||||
// casPVListChan::~casPVListChan()
|
||||
//
|
||||
casPVListChan::~casPVListChan()
|
||||
{
|
||||
this->pv.removeChannel(*this);
|
||||
//
|
||||
// delete signal to PV occurs in
|
||||
// casChannelI::~casChannelI
|
||||
//
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.1.1.1 1996/06/20 00:28:16 jhill
|
||||
* ca server installation
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -46,17 +49,5 @@ inline casPVListChan::casPVListChan
|
||||
this->pv.installChannel(*this);
|
||||
}
|
||||
|
||||
//
|
||||
// casPVListChan::~casPVListChan()
|
||||
//
|
||||
inline casPVListChan::~casPVListChan()
|
||||
{
|
||||
this->pv.removeChannel(*this);
|
||||
//
|
||||
// delete signal to PV occurs in
|
||||
// casChannelI::~casChannelI
|
||||
//
|
||||
}
|
||||
|
||||
#endif // casPVListChanIL_h
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.11 1996/11/02 00:54:24 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.10 1996/09/16 18:24:05 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -150,7 +153,7 @@ inline caStatus casStrmClient::createChannel (const char *pName)
|
||||
// copied (not referenced) so we are ok if they wrap
|
||||
// pName through into retVal
|
||||
//
|
||||
status = createChanResponse (*this->ctx.getMsg(), retVal);
|
||||
status = this->createChanResponse (*this->ctx.getMsg(), retVal);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -1311,9 +1314,13 @@ caStatus casStrmClient::readSyncAction()
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* caStatus casStrmClient::accessRightsResponse()
|
||||
*/
|
||||
//
|
||||
// casStrmClient::accessRightsResponse()
|
||||
//
|
||||
// NOTE:
|
||||
// Do not change the size of this response without making
|
||||
// parallel changes in createChanResp
|
||||
//
|
||||
caStatus casStrmClient::accessRightsResponse(casChannelI *pciu)
|
||||
{
|
||||
caHdr *reply;
|
||||
@@ -1575,6 +1582,7 @@ caStatus createDBRDD (unsigned dbrType, aitIndex dbrCount, gdd *&pDescRet)
|
||||
aitUint32 valIndex;
|
||||
aitUint32 gddStatus;
|
||||
aitUint16 appType;
|
||||
gdd *pVal;
|
||||
|
||||
appType = gddDbrToAit[dbrType].app;
|
||||
|
||||
@@ -1586,40 +1594,92 @@ caStatus createDBRDD (unsigned dbrType, aitIndex dbrCount, gdd *&pDescRet)
|
||||
return S_cas_noMemory;
|
||||
}
|
||||
|
||||
//
|
||||
// set bounds for the value member
|
||||
//
|
||||
if (dbrCount != 1u) {
|
||||
if (pDescRet->isContainer()) {
|
||||
gddContainer *pCont = (gddContainer *) pDescRet;
|
||||
gdd *pVal;
|
||||
if (pDescRet->isContainer()) {
|
||||
gddContainer *pCont = (gddContainer *) pDescRet;
|
||||
|
||||
gddStatus =
|
||||
//
|
||||
// All DBR types have a value member
|
||||
//
|
||||
gddStatus =
|
||||
gddApplicationTypeTable::app_table.mapAppToIndex
|
||||
(appType, gddAppType_value, valIndex);
|
||||
if (gddStatus) {
|
||||
pDescRet->unreference();
|
||||
pDescRet = NULL;
|
||||
return S_cas_badType;
|
||||
}
|
||||
pVal = pCont->getDD(valIndex);
|
||||
assert (pVal);
|
||||
gddStatus = pVal->setBound (0, 0u, dbrCount);
|
||||
assert (gddStatus==0);
|
||||
if (gddStatus) {
|
||||
pDescRet->unreference();
|
||||
pDescRet = NULL;
|
||||
return S_cas_internal;
|
||||
}
|
||||
else if (pDescRet->isAtomic()) {
|
||||
gddAtomic *pAtomic = (gddAtomic *) pDescRet;
|
||||
gddStatus = pAtomic->setBound(0, 0u, dbrCount);
|
||||
assert (gddStatus==0);
|
||||
pVal = pCont->getDD(valIndex);
|
||||
if (!pVal) {
|
||||
pDescRet->unreference();
|
||||
pDescRet = NULL;
|
||||
return S_cas_internal;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pVal = pDescRet;
|
||||
}
|
||||
|
||||
if (pVal->isScalar()) {
|
||||
if (dbrCount<=1u) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// scaler and managed (and need to set the bounds)
|
||||
// => out of luck (cant modify bounds)
|
||||
//
|
||||
if (pDescRet->isManaged()) {
|
||||
pDescRet->unreference();
|
||||
pDescRet = NULL;
|
||||
return S_cas_internal;
|
||||
}
|
||||
|
||||
//
|
||||
// convert to atomic
|
||||
//
|
||||
pVal->setDimension(1);
|
||||
pVal->setBound(0, 0u, dbrCount);
|
||||
}
|
||||
else if (pVal->isAtomic()) {
|
||||
const gddBounds* pB = pVal->getBounds();
|
||||
aitIndex bound = dbrCount;
|
||||
unsigned dim;
|
||||
int modAllowed;
|
||||
|
||||
if (pDescRet->isManaged() || pDescRet->isFlat()) {
|
||||
modAllowed = FALSE;
|
||||
}
|
||||
else {
|
||||
assert (dbrCount==1u);
|
||||
modAllowed = TRUE;
|
||||
}
|
||||
|
||||
for (dim=0u; dim<(unsigned)pVal->dimension(); dim++) {
|
||||
if (pB->first()!=0u && pB->size()!=bound) {
|
||||
if (modAllowed) {
|
||||
pVal->setBound(dim, 0u, bound);
|
||||
}
|
||||
else {
|
||||
pDescRet->unreference();
|
||||
pDescRet = NULL;
|
||||
return S_cas_internal;
|
||||
}
|
||||
}
|
||||
bound = 0u;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// the GDD is container or isnt any of the normal types
|
||||
//
|
||||
pDescRet->unreference();
|
||||
pDescRet = NULL;
|
||||
return S_cas_internal;
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// casStrmClient::userName()
|
||||
@@ -1648,6 +1708,7 @@ caStatus casStrmClient::createChanResponse(const caHdr &msg,
|
||||
casChannelI *pChanI;
|
||||
casPVI *pPV;
|
||||
caHdr *claim_reply;
|
||||
caHdr *dummy;
|
||||
unsigned dbrType;
|
||||
caStatus status;
|
||||
|
||||
@@ -1665,7 +1726,13 @@ caStatus casStrmClient::createChanResponse(const caHdr &msg,
|
||||
return this->channelCreateFailed(&msg, S_cas_badParameter);
|
||||
}
|
||||
|
||||
status = allocMsg (0u, &claim_reply);
|
||||
//
|
||||
// NOTE:
|
||||
// We are allocating enough space for both the claim
|
||||
// response and the access response so that we know for
|
||||
// certain that they will both be sent together.
|
||||
//
|
||||
status = this->allocMsg (sizeof(caHdr), &dummy);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
@@ -1698,6 +1765,19 @@ caStatus casStrmClient::createChanResponse(const caHdr &msg,
|
||||
|
||||
pChanI = (casChannelI *) pChan;
|
||||
|
||||
//
|
||||
// NOTE:
|
||||
// We are certain that the request will complete
|
||||
// here because we allocated enough space for this
|
||||
// and the claim response above.
|
||||
//
|
||||
status = casStrmClient::accessRightsResponse(pChanI);
|
||||
if (status) {
|
||||
errMessage(status, "incompplete channel create?");
|
||||
pChanI->clientDestroy();
|
||||
return this->channelCreateFailed(&msg, status);
|
||||
}
|
||||
|
||||
status = pPV->bestDBRType(dbrType);
|
||||
if (status) {
|
||||
errMessage(status, "best external dbr type fetch failed");
|
||||
@@ -1705,12 +1785,35 @@ caStatus casStrmClient::createChanResponse(const caHdr &msg,
|
||||
return this->channelCreateFailed(&msg, status);
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE:
|
||||
// We are allocated enough space for both the claim
|
||||
// response and the access response so that we know for
|
||||
// certain that they will both be sent together.
|
||||
// Nevertheles, some (old) clients do not receive
|
||||
// an access rights response so we allocate again
|
||||
// here to be certain that we are at the correct place in
|
||||
// the protocol buffer.
|
||||
//
|
||||
status = this->allocMsg (sizeof(caHdr), &claim_reply,
|
||||
FALSE /* dont lock the out buffer again*/);
|
||||
//
|
||||
// Not sending the access rights response and the claim
|
||||
// response is a severe error which is avoided by
|
||||
// the first (oversize) allocMsg
|
||||
//
|
||||
assert (status==S_cas_success);
|
||||
|
||||
*claim_reply = nill_msg;
|
||||
claim_reply->m_cmmd = CA_PROTO_CLAIM_CIU;
|
||||
claim_reply->m_type = dbrType;
|
||||
claim_reply->m_count = pPV->nativeCount();
|
||||
claim_reply->m_cid = msg.m_cid;
|
||||
claim_reply->m_available = pChanI->getSID();
|
||||
|
||||
//
|
||||
// Unlock the buffer (and convert it to network format
|
||||
//
|
||||
this->commitMsg();
|
||||
|
||||
return status;
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
* $Log$
|
||||
* Revision 1.9 1996/11/22 19:52:24 jhill
|
||||
* doc
|
||||
*
|
||||
* Revision 1.8 1996/11/22 19:22:53 jhill
|
||||
* doc
|
||||
*
|
||||
@@ -375,7 +378,7 @@ public:
|
||||
// where no clients are attached.
|
||||
// 2) once for all PVs that exist when the server is deleted
|
||||
//
|
||||
// the default destroy() executes "delete this"
|
||||
// the default (base) "destroy()" executes "delete this"
|
||||
//
|
||||
virtual void destroy ();
|
||||
|
||||
@@ -383,7 +386,52 @@ public:
|
||||
// tbe best type for clients to use when accessing the
|
||||
// value of the PV
|
||||
//
|
||||
virtual aitEnum bestExternalType ();
|
||||
virtual aitEnum bestExternalType () const;
|
||||
|
||||
//
|
||||
// Returns the maximum bounding box for all present and
|
||||
// future data stored within the PV.
|
||||
//
|
||||
// The routine "dimension()" returns the maximum
|
||||
// number of dimensions in the hypercube (0=scaler,
|
||||
// 1=array, 2=plane, 3=cube ...}.
|
||||
//
|
||||
// The routine "maxBound(dimension)" returns the
|
||||
// maximum length of a particular dimension of the
|
||||
// hypercube as follows:
|
||||
//
|
||||
// dim equal to 0 1 3 ...
|
||||
// -------------------------------------------
|
||||
// hypercube
|
||||
// type
|
||||
// ---------
|
||||
//
|
||||
// array array
|
||||
// length
|
||||
//
|
||||
// plane x y
|
||||
//
|
||||
// cube x y z
|
||||
//
|
||||
// .
|
||||
// .
|
||||
// .
|
||||
//
|
||||
// The default (base) "dimension()" returns zero (scaler).
|
||||
// The default (base) "maxBound()" returns scaler bounds
|
||||
// for all dimensions.
|
||||
//
|
||||
// Clients will see that the PV's data is scaler if
|
||||
// these routines are not supplied in the derived class.
|
||||
//
|
||||
// If the "dimension" argument to maxBounds() is set to
|
||||
// zero then the bound on the first dimension is being
|
||||
// fetched. If the "dimension" argument to maxBound() is
|
||||
// set to one then the bound on the second dimension
|
||||
// are being fetched...
|
||||
//
|
||||
virtual unsigned maxDimension() const; // return zero if scaler
|
||||
virtual aitIndex maxBound (unsigned dimension) const;
|
||||
|
||||
//
|
||||
// Server tool calls this function to post a PV event.
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.5 1996/11/02 00:54:30 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.4 1996/09/16 18:24:07 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -91,7 +94,8 @@ outBuf::~outBuf()
|
||||
//
|
||||
caStatus outBuf::allocMsg (
|
||||
bufSizeT extsize, // extension size
|
||||
caHdr **ppMsg
|
||||
caHdr **ppMsg,
|
||||
int lockRequired
|
||||
)
|
||||
{
|
||||
bufSizeT msgsize;
|
||||
@@ -106,7 +110,14 @@ caHdr **ppMsg
|
||||
|
||||
stackNeeded = this->bufSize - msgsize;
|
||||
|
||||
this->mutex.osiLock();
|
||||
//
|
||||
// In some special situations we preallocate space for
|
||||
// two messages and prefer not to lock twice
|
||||
// (so that lock/unlock pairs will match)
|
||||
//
|
||||
if (lockRequired) {
|
||||
this->mutex.osiLock();
|
||||
}
|
||||
|
||||
if (this->stack > stackNeeded) {
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.12 1996/11/02 00:54:31 jhill
|
||||
* many improvements
|
||||
*
|
||||
* Revision 1.11 1996/09/16 18:24:09 jhill
|
||||
* vxWorks port changes
|
||||
*
|
||||
@@ -353,7 +356,7 @@ public:
|
||||
// allocate message buffer space
|
||||
// (leaves message buffer locked)
|
||||
//
|
||||
caStatus allocMsg (unsigned extsize, caHdr **ppMsg);
|
||||
caStatus allocMsg (unsigned extsize, caHdr **ppMsg, int lockRequired=1);
|
||||
|
||||
//
|
||||
// commits message allocated with allocMsg()
|
||||
|
||||
Reference in New Issue
Block a user