fix for mantis 296
This commit is contained in:
+89
-74
@@ -493,12 +493,12 @@ LOCAL void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
struct event_ext *pevext = pArg;
|
||||
struct client *pClient = pevext->pciu->client;
|
||||
struct channel_in_use *pciu = pevext->pciu;
|
||||
const int readAccess = asCheckGet ( pciu->asClientPVT );
|
||||
int status;
|
||||
int strcnt;
|
||||
int v41;
|
||||
|
||||
if ( pevext->send_lock )
|
||||
SEND_LOCK ( pClient );
|
||||
SEND_LOCK ( pClient );
|
||||
|
||||
/*
|
||||
* New clients recv the status of the
|
||||
@@ -526,22 +526,19 @@ LOCAL void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
"server unable to load read (or subscription update) response into protocol buffer PV=\"%s\" max bytes=%u",
|
||||
RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP );
|
||||
if ( ! eventsRemaining )
|
||||
cas_send_bs_msg ( pClient, ! pevext->send_lock );
|
||||
if ( pevext->send_lock )
|
||||
SEND_UNLOCK ( pClient );
|
||||
cas_send_bs_msg ( pClient, FALSE );
|
||||
SEND_UNLOCK ( pClient );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* verify read access
|
||||
*/
|
||||
if ( ! asCheckGet ( pciu->asClientPVT ) ) {
|
||||
if ( ! readAccess ) {
|
||||
no_read_access_event ( pClient, pevext );
|
||||
if ( ! eventsRemaining )
|
||||
cas_send_bs_msg ( pClient, !pevext->send_lock );
|
||||
if ( pevext->send_lock ) {
|
||||
SEND_UNLOCK ( pClient );
|
||||
}
|
||||
cas_send_bs_msg ( pClient, FALSE );
|
||||
SEND_UNLOCK ( pClient );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -606,10 +603,9 @@ LOCAL void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
* them up like db requests when the OPI does not keep up.
|
||||
*/
|
||||
if ( ! eventsRemaining )
|
||||
cas_send_bs_msg ( pClient, ! pevext->send_lock );
|
||||
cas_send_bs_msg ( pClient, FALSE );
|
||||
|
||||
if ( pevext->send_lock )
|
||||
SEND_UNLOCK ( pClient );
|
||||
SEND_UNLOCK ( pClient );
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -619,14 +615,14 @@ LOCAL void read_reply ( void *pArg, struct dbAddr *paddr,
|
||||
*/
|
||||
LOCAL int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *pClient )
|
||||
{
|
||||
struct channel_in_use *pciu;
|
||||
struct channel_in_use *pciu = MPTOPCIU ( mp );
|
||||
const int readAccess = asCheckGet ( pciu->asClientPVT );
|
||||
ca_uint32_t payloadSize;
|
||||
void *pPayload;
|
||||
int status;
|
||||
int strcnt;
|
||||
int v41;
|
||||
|
||||
pciu = MPTOPCIU ( mp );
|
||||
if ( ! pciu ) {
|
||||
logBadId ( pClient, mp, 0 );
|
||||
return RSRV_ERROR;
|
||||
@@ -655,7 +651,7 @@ LOCAL int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *pC
|
||||
* verify read access
|
||||
*/
|
||||
v41 = CA_V41 ( pClient->minor_version_number );
|
||||
if ( ! asCheckGet ( pciu->asClientPVT ) ) {
|
||||
if ( ! readAccess ) {
|
||||
if ( v41 ) {
|
||||
status = ECA_NORDACCESS;
|
||||
}
|
||||
@@ -719,7 +715,6 @@ LOCAL int read_notify_action ( caHdrLargeArray *mp, void *pPayload, struct clien
|
||||
|
||||
evext.msg = *mp;
|
||||
evext.pciu = pciu;
|
||||
evext.send_lock = TRUE;
|
||||
evext.pdbev = NULL;
|
||||
evext.size = dbr_size_n ( mp->m_dataType, mp->m_count );
|
||||
|
||||
@@ -1038,7 +1033,7 @@ unsigned cid
|
||||
}
|
||||
|
||||
epicsMutexMustLock( client->chanListLock );
|
||||
pchannel->state = rsrvCS_inService;
|
||||
pchannel->state = rsrvCS_pendConnectResp;
|
||||
ellAdd ( &client->chanList, &pchannel->node );
|
||||
epicsMutexUnlock ( client->chanListLock );
|
||||
|
||||
@@ -1071,9 +1066,16 @@ LOCAL void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
|
||||
{
|
||||
case asClientCOAR:
|
||||
{
|
||||
const int readAccess = asCheckGet ( pciu->asClientPVT );
|
||||
unsigned sigReq = 0;
|
||||
|
||||
epicsMutexMustLock ( pclient->chanListLock );
|
||||
if ( pciu->state == rsrvCS_pendConnectResp ) {
|
||||
ellDelete ( &pclient->chanList, &pciu->node );
|
||||
pciu->state = rsrvCS_pendConnectRespUpdatePendAR;
|
||||
ellAdd ( &pclient->chanPendingUpdateARList, &pciu->node );
|
||||
sigReq = 1;
|
||||
}
|
||||
if ( pciu->state == rsrvCS_inService ) {
|
||||
ellDelete ( &pclient->chanList, &pciu->node );
|
||||
pciu->state = rsrvCS_inServiceUpdatePendAR;
|
||||
@@ -1083,23 +1085,22 @@ LOCAL void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
|
||||
epicsMutexUnlock ( pclient->chanListLock );
|
||||
|
||||
/*
|
||||
* Update all event call backs
|
||||
*/
|
||||
* Update all event call backs
|
||||
*/
|
||||
epicsMutexMustLock(pclient->eventqLock);
|
||||
|
||||
for (pevext = (struct event_ext *) ellFirst(&pciu->eventq);
|
||||
pevext;
|
||||
pevext = (struct event_ext *) ellNext(&pevext->node)){
|
||||
|
||||
int readAccess = asCheckGet(pciu->asClientPVT);
|
||||
|
||||
if(pevext->pdbev && !readAccess){
|
||||
db_post_single_event(pevext->pdbev);
|
||||
db_event_disable(pevext->pdbev);
|
||||
}
|
||||
else if(pevext->pdbev && readAccess){
|
||||
db_event_enable(pevext->pdbev);
|
||||
db_post_single_event(pevext->pdbev);
|
||||
if ( pevext->pdbev ) {
|
||||
if ( readAccess ){
|
||||
db_event_enable ( pevext->pdbev );
|
||||
db_post_single_event ( pevext->pdbev );
|
||||
}
|
||||
else {
|
||||
db_post_single_event ( pevext->pdbev );
|
||||
db_event_disable ( pevext->pdbev );
|
||||
}
|
||||
}
|
||||
}
|
||||
epicsMutexUnlock(pclient->eventqLock);
|
||||
@@ -1155,13 +1156,50 @@ LOCAL void access_rights_reply ( struct channel_in_use * pciu )
|
||||
SEND_UNLOCK ( pciu->client );
|
||||
}
|
||||
|
||||
/*
|
||||
* claim_ciu_reply()
|
||||
*/
|
||||
LOCAL void claim_ciu_reply ( struct channel_in_use * pciu )
|
||||
{
|
||||
int v42 = CA_V42 ( pciu->client->minor_version_number );
|
||||
access_rights_reply ( pciu );
|
||||
if ( v42 ) {
|
||||
int status;
|
||||
ca_uint32_t nElem;
|
||||
SEND_LOCK ( pciu->client );
|
||||
if ( pciu->addr.no_elements < 0 ) {
|
||||
nElem = 0;
|
||||
}
|
||||
else {
|
||||
if ( ! CA_V49 ( pciu->client->minor_version_number ) ) {
|
||||
if ( pciu->addr.no_elements >= 0xffff ) {
|
||||
nElem = 0xfffe;
|
||||
}
|
||||
else {
|
||||
nElem = (ca_uint32_t) pciu->addr.no_elements;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nElem = (ca_uint32_t) pciu->addr.no_elements;
|
||||
}
|
||||
}
|
||||
status = cas_copy_in_header (
|
||||
pciu->client, CA_PROTO_CREATE_CHAN, 0u,
|
||||
pciu->addr.dbr_field_type, nElem, pciu->cid,
|
||||
pciu->sid, NULL );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
cas_commit_msg ( pciu->client, 0u );
|
||||
}
|
||||
SEND_UNLOCK(pciu->client);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* claim_ciu_action()
|
||||
*/
|
||||
LOCAL int claim_ciu_action ( caHdrLargeArray *mp,
|
||||
void *pPayload, client *client )
|
||||
{
|
||||
int v42;
|
||||
int status;
|
||||
struct channel_in_use *pciu;
|
||||
|
||||
@@ -1263,7 +1301,7 @@ LOCAL int claim_ciu_action ( caHdrLargeArray *mp,
|
||||
epicsMutexUnlock(prsrv_cast_client->chanListLock);
|
||||
|
||||
epicsMutexMustLock(client->chanListLock);
|
||||
pciu->state = rsrvCS_inService;
|
||||
pciu->state = rsrvCS_pendConnectResp;
|
||||
pciu->client = client;
|
||||
ellAdd(&client->chanList, &pciu->node);
|
||||
epicsMutexUnlock(client->chanListLock);
|
||||
@@ -1293,19 +1331,17 @@ LOCAL int claim_ciu_action ( caHdrLargeArray *mp,
|
||||
*/
|
||||
asPutClientPvt(pciu->asClientPVT, pciu);
|
||||
|
||||
v42 = CA_V42(client->minor_version_number);
|
||||
|
||||
/*
|
||||
* register for asynch updates of access rights changes
|
||||
*/
|
||||
status = asRegisterClientCallback(
|
||||
pciu->asClientPVT,
|
||||
casAccessRightsCB);
|
||||
if(status == S_asLib_asNotActive){
|
||||
if ( status == S_asLib_asNotActive ) {
|
||||
/*
|
||||
* force the initial update
|
||||
* force the initial AR update followed by claim response
|
||||
*/
|
||||
access_rights_reply(pciu);
|
||||
claim_ciu_reply ( pciu );
|
||||
}
|
||||
else if (status!=0) {
|
||||
log_header ("No room for access security state change subscription",
|
||||
@@ -1316,37 +1352,6 @@ LOCAL int claim_ciu_action ( caHdrLargeArray *mp,
|
||||
SEND_UNLOCK(client);
|
||||
return RSRV_ERROR;
|
||||
}
|
||||
|
||||
if(v42){
|
||||
ca_uint32_t nElem;
|
||||
|
||||
SEND_LOCK ( client );
|
||||
|
||||
if ( pciu->addr.no_elements < 0 ) {
|
||||
nElem = 0;
|
||||
}
|
||||
else {
|
||||
if ( ! CA_V49 ( client->minor_version_number ) ) {
|
||||
if ( pciu->addr.no_elements >= 0xffff ) {
|
||||
nElem = 0xfffe;
|
||||
}
|
||||
else {
|
||||
nElem = (ca_uint32_t) pciu->addr.no_elements;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nElem = (ca_uint32_t) pciu->addr.no_elements;
|
||||
}
|
||||
}
|
||||
status = cas_copy_in_header (
|
||||
client, CA_PROTO_CREATE_CHAN, 0u,
|
||||
pciu->addr.dbr_field_type, nElem, pciu->cid,
|
||||
pciu->sid, NULL );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
cas_commit_msg ( client, 0u );
|
||||
}
|
||||
SEND_UNLOCK(client);
|
||||
}
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
@@ -1479,9 +1484,19 @@ LOCAL void sendAllUpdateAS ( struct client *client )
|
||||
pciu = ( struct channel_in_use * )
|
||||
ellGet ( & client->chanPendingUpdateARList );
|
||||
while ( pciu ) {
|
||||
access_rights_reply ( pciu );
|
||||
if ( pciu->state == rsrvCS_pendConnectRespUpdatePendAR ) {
|
||||
claim_ciu_reply ( pciu );
|
||||
}
|
||||
else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ) {
|
||||
access_rights_reply ( pciu );
|
||||
}
|
||||
else {
|
||||
errlogPrintf (
|
||||
"%s at %d: corrupt channel state detected durring AR update\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
pciu->state = rsrvCS_inService;
|
||||
ellAdd ( & client->chanList, &pciu->node );
|
||||
ellAdd ( & client->chanList, & pciu->node );
|
||||
pciu = ( struct channel_in_use * )
|
||||
ellGet ( & client->chanPendingUpdateARList );
|
||||
}
|
||||
@@ -1501,7 +1516,6 @@ void rsrv_extra_labor ( void * pArg )
|
||||
cas_send_bs_msg ( pClient, TRUE );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* putNotifyErrorReply
|
||||
*/
|
||||
@@ -1825,7 +1839,6 @@ LOCAL int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client *
|
||||
|
||||
pevext->msg = *mp;
|
||||
pevext->pciu = pciu;
|
||||
pevext->send_lock = TRUE;
|
||||
pevext->size = dbr_size_n(mp->m_dataType, mp->m_count);
|
||||
pevext->mask = ntohs ( pmi->m_mask );
|
||||
|
||||
@@ -1945,10 +1958,12 @@ LOCAL int clear_channel_reply ( caHdrLargeArray *mp,
|
||||
SEND_UNLOCK(client);
|
||||
|
||||
epicsMutexMustLock ( client->chanListLock );
|
||||
if ( pciu->state == rsrvCS_inService ) {
|
||||
if ( pciu->state == rsrvCS_inService ||
|
||||
! pciu->state == rsrvCS_pendConnectResp ) {
|
||||
ellDelete ( &client->chanList, &pciu->node );
|
||||
}
|
||||
else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ) {
|
||||
else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ||
|
||||
! pciu->state == rsrvCS_pendConnectRespUpdatePendAR ) {
|
||||
ellDelete ( &client->chanPendingUpdateARList, &pciu->node );
|
||||
}
|
||||
else {
|
||||
|
||||
+5
-3
@@ -104,8 +104,11 @@ typedef struct client {
|
||||
|
||||
enum rsrvChanState {
|
||||
rsrvCS_invalid,
|
||||
rsrvCS_inService,
|
||||
rsrvCS_inServiceUpdatePendAR };
|
||||
rsrvCS_pendConnectResp,
|
||||
rsrvCS_inService,
|
||||
rsrvCS_pendConnectRespUpdatePendAR,
|
||||
rsrvCS_inServiceUpdatePendAR
|
||||
};
|
||||
|
||||
/*
|
||||
* per channel structure
|
||||
@@ -136,7 +139,6 @@ struct event_ext {
|
||||
unsigned size; /* for speed */
|
||||
unsigned mask;
|
||||
char modified; /* mod & ev flw ctrl enbl */
|
||||
char send_lock; /* lock send buffer */
|
||||
};
|
||||
|
||||
/* NOTE: external used so they remember the state across loads */
|
||||
|
||||
Reference in New Issue
Block a user