fix for mantis 296

This commit is contained in:
Jeff Hill
2007-08-17 22:31:11 +00:00
parent 2c7af24445
commit b5e2b40be0
2 changed files with 94 additions and 77 deletions
+89 -74
View File
@@ -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
View File
@@ -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 */