Index: camessage.c =================================================================== RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/rsrv/camessage.c,v retrieving revision 1.105.2.9 diff -u -b -r1.105.2.9 camessage.c --- camessage.c 28 Nov 2006 18:50:53 -0000 1.105.2.9 +++ camessage.c 7 Nov 2007 19:02:45 -0000 @@ -493,11 +493,11 @@ 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 ); /* @@ -526,8 +526,7 @@ "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 ) + cas_send_bs_msg ( pClient, FALSE ); SEND_UNLOCK ( pClient ); return; } @@ -535,13 +534,11 @@ /* * 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 ) { + cas_send_bs_msg ( pClient, FALSE ); SEND_UNLOCK ( pClient ); - } return; } @@ -606,9 +603,8 @@ * 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 ); return; @@ -619,14 +615,14 @@ */ 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 @@ * 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 @@ 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 @@ } epicsMutexMustLock( client->chanListLock ); - pchannel->state = rsrvCS_inService; + pchannel->state = rsrvCS_pendConnectResp; ellAdd ( &client->chanList, &pchannel->node ); epicsMutexUnlock ( client->chanListLock ); @@ -1071,10 +1066,17 @@ { case asClientCOAR: { + const int readAccess = asCheckGet ( pciu->asClientPVT ); unsigned sigReq = 0; epicsMutexMustLock ( pclient->chanListLock ); - if ( pciu->state == rsrvCS_inService ) { + if ( pciu->state == rsrvCS_pendConnectResp ) { + ellDelete ( &pclient->chanList, &pciu->node ); + pciu->state = rsrvCS_pendConnectRespUpdatePendAR; + ellAdd ( &pclient->chanPendingUpdateARList, &pciu->node ); + sigReq = 1; + } + else if ( pciu->state == rsrvCS_inService ) { ellDelete ( &pclient->chanList, &pciu->node ); pciu->state = rsrvCS_inServiceUpdatePendAR; ellAdd ( &pclient->chanPendingUpdateARList, &pciu->node ); @@ -1086,20 +1088,19 @@ * 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); + 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 ); } - else if(pevext->pdbev && readAccess){ - db_event_enable(pevext->pdbev); - db_post_single_event(pevext->pdbev); } } epicsMutexUnlock(pclient->eventqLock); @@ -1156,12 +1157,49 @@ } /* + * 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 @@ 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,20 @@ */ 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 ) { + epicsMutexMustLock ( client->chanListLock ); + pciu->state = rsrvCS_inService; + epicsMutexUnlock ( client->chanListLock ); /* - * 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 +1355,6 @@ 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 +1487,19 @@ pciu = ( struct channel_in_use * ) ellGet ( & client->chanPendingUpdateARList ); while ( 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 +1519,6 @@ cas_send_bs_msg ( pClient, TRUE ); } - /* * putNotifyErrorReply */ @@ -1825,7 +1842,6 @@ 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 +1961,12 @@ 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 { @@ -1965,7 +1983,6 @@ * remove from access control list */ status = asRemoveClient(&pciu->asClientPVT); - assert(status == 0 || status == S_asLib_asNotActive); if(status != 0 && status != S_asLib_asNotActive){ errMessage(status, RECORD_NAME(&pciu->addr)); return RSRV_ERROR; Index: server.h =================================================================== RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/rsrv/server.h,v retrieving revision 1.70 retrieving revision 1.67.2.4 diff -u -b -r1.70 -r1.67.2.4 --- server.h 29 Nov 2006 17:51:30 -0000 1.70 +++ server.h 17 Aug 2007 22:31:11 -0000 1.67.2.4 @@ -104,8 +104,11 @@ enum rsrvChanState { rsrvCS_invalid, + rsrvCS_pendConnectResp, rsrvCS_inService, - rsrvCS_inServiceUpdatePendAR }; + rsrvCS_pendConnectRespUpdatePendAR, + rsrvCS_inServiceUpdatePendAR +}; /* * per channel structure @@ -136,7 +139,6 @@ 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 */