diff --git a/src/ca/access.c b/src/ca/access.c index 7e6fd21e0..aacc3502f 100644 --- a/src/ca/access.c +++ b/src/ca/access.c @@ -280,10 +280,12 @@ void *pext; { struct extmsg msg; unsigned long bytesAvailable; + unsigned long actualextsize; unsigned long extsize; unsigned long bytesSent; msg = *pmsg; + actualextsize = pmsg->m_postsize; extsize = CA_MESSAGE_ALIGN(pmsg->m_postsize); msg.m_postsize = htons(extsize); @@ -342,8 +344,26 @@ void *pext; bytesSent = cacRingBufferWrite( &piiu->send, pext, - extsize); - assert(bytesSent == extsize); + actualextsize); + assert(bytesSent == actualextsize); + /* + * force pad bytes at the end of the message to nill + * if present + */ + { + static nullBuff[32]; + int n; + + n = extsize-actualextsize; + if(n){ + assert(n<=sizeof(nullBuff)); + bytesSent = cacRingBufferWrite( + &piiu->send, + nullBuff, + n); + assert(bytesSent == n); + } + } UNLOCK; @@ -1557,6 +1577,10 @@ void *pvalue if (INVALID_DB_REQ(type)) return ECA_BADTYPE; + if(!chix->ar.read_access){ + return ECA_NORDACCESS; + } + if (count > chix->count) return ECA_BADCOUNT; @@ -1633,6 +1657,9 @@ int ca_array_get_callback if (count > chix->count) return ECA_BADCOUNT; + if(!chix->ar.read_access){ + return ECA_NORDACCESS; + } #ifdef vxWorks if (!chix->piiu) { @@ -1768,6 +1795,10 @@ void *usrarg; if(INVALID_DB_FIELD(type)) return ECA_BADTYPE; + if(!chix->ar.write_access){ + return ECA_NOWTACCESS; + } + /* * check for valid count */ @@ -2054,6 +2085,10 @@ void *pvalue; if(INVALID_DB_FIELD(type)) return ECA_BADTYPE; + if(!chix->ar.write_access){ + return ECA_NOWTACCESS; + } + /* * check for valid count */ diff --git a/src/ca/acctst.c b/src/ca/acctst.c index 11a45bd1e..3eaedb54f 100644 --- a/src/ca/acctst.c +++ b/src/ca/acctst.c @@ -210,6 +210,10 @@ char *pname; NULL, CONN_ROUTINE, NULL), NULL); +#if 0 + status = ca_replace_access_rights_event(chix1, ar_event); + SEVCHK(status,NULL); +#endif status = ca_pend_io(1000.0); SEVCHK(status, NULL); @@ -238,6 +242,10 @@ char *pname; lib$init_timer(); #endif /*VMS*/ + printf("Read Access=%d Write Access=%d\n", + ca_read_access(chix1), + ca_write_access(chix1)); + /* * verify we dont jam up on many uninterrupted * solicitations @@ -453,7 +461,7 @@ char *pname; assert(conn_get_cb_count == 3); printf("-- Put/Gets done- waiting for Events --\n"); - status = ca_pend_event(2000.0); + status = ca_pend_event(10.0); if (status == ECA_TIMEOUT) { free(ptr); diff --git a/src/ca/iocinf.c b/src/ca/iocinf.c index 5e7dcaf4b..e8d4e0635 100644 --- a/src/ca/iocinf.c +++ b/src/ca/iocinf.c @@ -1425,9 +1425,10 @@ struct ioc_in_use *piiu; chix->count = 0; chix->state = cs_prev_conn; chix->id.sid = ~0L; + chix->ar.read_access = FALSE; + chix->ar.write_access = FALSE; } - /* * remove IOC from the hash table */ @@ -1460,18 +1461,18 @@ struct ioc_in_use *piiu; chix = (chid) &piiu->chidlist.node.next; while(chix = (chid) chix->node.next){ LOCKEVENTS; - if(chix->access_rights_func){ - struct access_rights_handler_args args; - args.chid = chix; - args.ar = chix->ar; - (*chix->access_rights_func)(args); - } if(chix->connection_func){ struct connection_handler_args args; args.chid = chix; args.op = CA_OP_CONN_DOWN; (*chix->connection_func)(args); } + if(chix->access_rights_func){ + struct access_rights_handler_args args; + args.chid = chix; + args.ar = chix->ar; + (*chix->access_rights_func)(args); + } UNLOCKEVENTS; chix->piiu = piiuCast; } diff --git a/src/ca/iocmsg.h b/src/ca/iocmsg.h index b555205f3..3cbbc82aa 100644 --- a/src/ca/iocmsg.h +++ b/src/ca/iocmsg.h @@ -59,6 +59,7 @@ static char *iocmsghSccsId = "$Id$ CA version 4.1"; #define IOC_WRITE_NOTIFY 19 /* notify after write chan value */ #define IOC_CLIENT_NAME 20 /* CA V4.1 identify client */ #define IOC_HOST_NAME 21 /* CA V4.1 identify client */ +#define IOC_ACCESS_RIGHTS 22 /* CA V4.1 asynch access rights chg */ /* * for use with build and search and not_found (if search fails and @@ -79,6 +80,14 @@ static char *iocmsghSccsId = "$Id$ CA version 4.1"; #define BI_ROUND(A) ((((unsigned long)A)+1)>>1) #define BI_SIZEOF(A) (BI_ROUND(sizeof(A))) +/* + * For communicating access rights to the clients + * + * (placed in m_available hdr field of IOC_ACCESS_RIGHTS cmmd + */ +#define CA_ACCESS_RIGHT_READ (1<<0) +#define CA_ACCESS_RIGHT_WRITE (1<<1) + /* * Required Message Alignment * diff --git a/src/ca/os_depen.h b/src/ca/os_depen.h index dd203daf6..c0bb4ca81 100644 --- a/src/ca/os_depen.h +++ b/src/ca/os_depen.h @@ -112,7 +112,7 @@ static char *os_depenhSccsId = "$Id$"; #endif /*VMS*/ #ifndef CA_OS_CONFIGURED -/* # error Please define one of vxWorks, UNIX or VMS */ +@@@@@@ Please define one of vxWorks, UNIX or VMS @@@@@@ #endif #ifndef NULL diff --git a/src/ca/service.c b/src/ca/service.c index ce05d3fbc..ae18db309 100644 --- a/src/ca/service.c +++ b/src/ca/service.c @@ -648,6 +648,29 @@ struct in_addr *pnet_addr; UNLOCKEVENTS; break; } + case IOC_ACCESS_RIGHTS: + { + int ar; + chid chan; + + LOCK; + chan = bucketLookupItem(pBucket, piiu->curMsg.m_cid); + UNLOCK; + assert(chan); + + ar = ntohl(piiu->curMsg.m_available); + chan->ar.read_access = (ar&CA_ACCESS_RIGHT_READ)?1:0; + chan->ar.write_access = (ar&CA_ACCESS_RIGHT_WRITE)?1:0; + + if (chan->access_rights_func) { + struct access_rights_handler_args args; + + args.chid = chan; + args.ar = chan->ar; + (*chan->access_rights_func) (args); + } + break; + } default: ca_printf("CAC: post_msg(): Corrupt cmd in msg %x\n", piiu->curMsg.m_cmmd); @@ -683,6 +706,7 @@ struct in_addr *pnet_addr; IIU *allocpiiu; IIU *chpiiu; unsigned short *pMinorVersion; + int v41; /* * ignore broadcast replies for deleted channels @@ -758,6 +782,18 @@ struct in_addr *pnet_addr; chan->count = piiu->curMsg.m_count; chan->id.sid = piiu->curMsg.m_cid; + /* + * Assume that we have access once connected briefly + * until the server is able to tell us the correct + * state for backwards compatibility. + * + * Their access rights call back does not get + * called for the first time until the information + * arrives however. + */ + chan->ar.read_access = TRUE; + chan->ar.write_access = TRUE; + /* * Starting with CA V4.1 the minor version number * is appended to the end of each search reply. @@ -771,6 +807,10 @@ struct in_addr *pnet_addr; allocpiiu->minor_version_number = CA_UKN_MINOR_VERSION; } + v41 = CA_V41( + CA_PROTOCOL_VERSION, + allocpiiu->minor_version_number); + if(chpiiu != allocpiiu){ /* @@ -850,6 +890,20 @@ struct in_addr *pnet_addr; CLRPENDRECV(TRUE); } + /* + * if less than v4.1 then the server will never + * send access rights so we know that there + * will always be access and call their call back + * here + */ + if (chan->access_rights_func && !v41) { + struct access_rights_handler_args args; + + args.chid = chan; + args.ar = chan->ar; + (*chan->access_rights_func) (args); + } + UNLOCK; } diff --git a/src/rsrv/camessage.c b/src/rsrv/camessage.c index 4a9f6702b..303c5cac7 100644 --- a/src/rsrv/camessage.c +++ b/src/rsrv/camessage.c @@ -164,6 +164,11 @@ ASCLIENTPVT ascpvt, asClientStatus type ); +LOCAL void no_read_access_event( +struct client *client, +struct event_ext *pevext +); + LOCAL unsigned long bucketID; @@ -255,10 +260,11 @@ struct message_buffer *recv break; } - evext.mp = mp; + evext.msg = *mp; evext.pciu = pciu; evext.send_lock = TRUE; evext.get = TRUE; + evext.pdbev = NULL; evext.size = dbr_size_n(mp->m_type, mp->m_count); /* @@ -569,7 +575,9 @@ struct client *client &prsrv_cast_client->addrq, &pciu->node); UNLOCK_CLIENT(prsrv_cast_client); + pciu->client = client; + LOCK_CLIENT(client); ellAdd(&client->addrq, &pciu->node); UNLOCK_CLIENT(client); @@ -582,6 +590,13 @@ struct client *client */ pciu->client->minor_version_number = mp->m_available; + /* + * register for asynch updates of access rights changes + * (only after the lock is released, we are added to + * the correct client, and the clients version is + * known) + */ + asRegisterClientCallback(pciu->asClientPVT, casAccessRightsCB); } @@ -935,21 +950,36 @@ struct client *client } memset(pevext,0,size); pevext->msg = *mp; - pevext->mp = &pevext->msg; /* for speed- see - * IOC_READ */ pevext->pciu = pciu; pevext->send_lock = TRUE; pevext->size = dbr_size_n(mp->m_type, mp->m_count); + pevext->mask = ((struct monops *) mp)->m_info.m_mask; pevext->get = FALSE; + LOCK_CLIENT(client); + ellAdd( &pciu->eventq, &pevext->node); + UNLOCK_CLIENT(client); + + /* + * dont set up the event if no read access + */ + if(!asCheckGet(pciu->asClientPVT)){ + pevext->pdbev = NULL; + no_read_access_event(client, pevext); + return; + } + + pevext->pdbev = (struct event_block *)(pevext+1); + status = db_add_event( client->evuser, &pciu->addr, read_reply, pevext, - (unsigned) ((struct monops *) mp)->m_info.m_mask, - (struct event_block *)(pevext+1)); + pevext->mask, + pevext->pdbev); if (status == ERROR) { + pevext->pdbev = NULL; LOCK_CLIENT(client); send_err( mp, @@ -957,21 +987,9 @@ struct client *client client, RECORD_NAME(&pciu->addr)); UNLOCK_CLIENT(client); - FASTLOCK(&rsrv_free_eventq_lck); - ellAdd(&rsrv_free_eventq, &pevext->node); - FASTUNLOCK(&rsrv_free_eventq_lck); return; } - /* - * Only add to the list if we can get enough - * memory. If not, attempts to delete it - * from the client will cause a warning message - * to be printed since it will not be found on - * the list. - */ - ellAdd( &pciu->eventq, &pevext->node); - /* * always send it once at event add */ @@ -998,7 +1016,7 @@ struct client *client * messages sent by the server). */ - db_post_single_event((struct event_block *)(pevext+1)); + db_post_single_event(pevext->pdbev); return; } @@ -1016,10 +1034,10 @@ struct extmsg *mp, struct client *client ) { - FAST struct extmsg *reply; - FAST struct event_ext *pevext; + struct extmsg *reply; + struct event_ext *pevext; struct channel_in_use *pciu; - FAST int status; + int status; /* * @@ -1041,11 +1059,18 @@ struct client *client } } - while (pevext = (struct event_ext *) ellGet(&pciu->eventq)) { + while (TRUE){ + LOCK_CLIENT(client); + pevext = (struct event_ext *) ellGet(&pciu->eventq); + UNLOCK_CLIENT(client); - status = db_cancel_event((struct event_block *)(pevext+1)); - if (status){ - taskSuspend(0); + if(!pevext){ + break; + } + + if(pevext->pdbev){ + status = db_cancel_event(pevext->pdbev); + assert(status == OK); } FASTLOCK(&rsrv_free_eventq_lck); ellAdd(&rsrv_free_eventq, &pevext->node); @@ -1111,11 +1136,10 @@ struct extmsg *mp, struct client *client ) { - struct extmsg *reply; - struct event_ext *pevext; - ELLLIST *peventq; - int status; - struct channel_in_use *pciu; + struct channel_in_use *pciu; + struct extmsg *reply; + struct event_ext *pevext; + int status; /* * @@ -1127,46 +1151,60 @@ struct client *client logBadId(client, mp); return; } - peventq = &pciu->eventq; - for (pevext = (struct event_ext *) peventq->node.next; - pevext; - pevext = (struct event_ext *) pevext->node.next) - if (pevext->msg.m_available == mp->m_available) { - status = db_cancel_event((struct event_block *)(pevext+1)); - if (status == ERROR) - taskSuspend(0); - ellDelete(peventq, &pevext->node); - - /* - * send delete confirmed message - */ - LOCK_CLIENT(client); - reply = (struct extmsg *) ALLOC_MSG(client, 0); - if (!reply) { - UNLOCK_CLIENT(client); - taskSuspend(0); - } - *reply = pevext->msg; - reply->m_postsize = 0; - - END_MSG(client); - UNLOCK_CLIENT(client); - - FASTLOCK(&rsrv_free_eventq_lck); - ellAdd(&rsrv_free_eventq, &pevext->node); - FASTUNLOCK(&rsrv_free_eventq_lck); - - return; - } /* - * Not Found- return an error message + * search events on this channel for a match + * (there are usually very few monitors per channel) */ LOCK_CLIENT(client); - send_err(mp, ECA_BADMONID, client, RECORD_NAME(&pciu->addr)); + for (pevext = (struct event_ext *) ellFirst(&pciu->eventq); + pevext; + pevext = (struct event_ext *) ellNext(&pevext->node)){ + + if (pevext->msg.m_available == mp->m_available) { + ellDelete(&pciu->eventq, &pevext->node); + break; + } + } UNLOCK_CLIENT(client); - return; + /* + * Not Found- return an exception event + */ + if(!pevext){ + LOCK_CLIENT(client); + send_err(mp, ECA_BADMONID, client, RECORD_NAME(&pciu->addr)); + UNLOCK_CLIENT(client); + return; + } + + + /* + * cancel monitor activity in progress + */ + if(pevext->pdbev){ + status = db_cancel_event(pevext->pdbev); + assert(status == OK); + } + + /* + * send delete confirmed message + */ + LOCK_CLIENT(client); + reply = (struct extmsg *) ALLOC_MSG(client, 0); + if (!reply) { + UNLOCK_CLIENT(client); + assert(0); + } + *reply = pevext->msg; + reply->m_postsize = 0; + + END_MSG(client); + UNLOCK_CLIENT(client); + + FASTLOCK(&rsrv_free_eventq_lck); + ellAdd(&rsrv_free_eventq, &pevext->node); + FASTUNLOCK(&rsrv_free_eventq_lck); } @@ -1185,7 +1223,6 @@ db_field_log *pfl ) { struct event_ext *pevext = pArg; - struct extmsg *mp = pevext->mp; struct client *client = pevext->pciu->client; struct channel_in_use *pciu = pevext->pciu; struct extmsg *reply; @@ -1206,18 +1243,18 @@ db_field_log *pfl reply = (struct extmsg *) ALLOC_MSG(client, pevext->size); if (!reply) { - send_err(mp, ECA_TOLARGE, client, RECORD_NAME(paddr)); + send_err(&pevext->msg, ECA_TOLARGE, client, RECORD_NAME(paddr)); + if (!eventsRemaining) + cas_send_msg(client,!pevext->send_lock); if (pevext->send_lock) UNLOCK_CLIENT(client); - if (!eventsRemaining) - cas_send_msg(client,FALSE); return; } /* * setup response message */ - *reply = *mp; + *reply = pevext->msg; reply->m_postsize = pevext->size; reply->m_cid = (unsigned long)pciu->cid; @@ -1226,52 +1263,37 @@ db_field_log *pfl */ v41 = CA_V41(CA_PROTOCOL_VERSION,client->minor_version_number); if(!asCheckGet(pciu->asClientPVT)){ - if(v41){ - status = ECA_NORDACCESS; - } - else{ - status = ECA_GETFAIL; - } - - /* - * I cant wait to redesign this protocol from scratch! - */ - if(!v41||reply->m_cmmd==IOC_READ||reply->m_cmmd==IOC_READ_BUILD){ + if(reply->m_cmmd==IOC_READ|| + reply->m_cmmd==IOC_READ_BUILD){ + if(v41){ + status = ECA_NORDACCESS; + } + else{ + status = ECA_GETFAIL; + } /* * old client & plain get & search/get * continue to return an exception * on failure */ - send_err(mp, status, client, RECORD_NAME(paddr)); + send_err(&pevext->msg, status, + client, RECORD_NAME(paddr)); } else{ - /* - * New clients recv the status of the - * operation directly to the - * event/put/get callback. - * - * Fetched value is zerod in case they - * use it even when the status indicates - * failure. - * - * The m_cid field in the protocol - * header is abused to carry the status - */ - bzero((char *)(reply+1), pevext->size); - reply->m_cid = status; - END_MSG(client); + no_read_access_event(client, pevext); } - if (pevext->send_lock) - UNLOCK_CLIENT(client); if (!eventsRemaining) - cas_send_msg(client,FALSE); + cas_send_msg(client,!pevext->send_lock); + if (pevext->send_lock){ + UNLOCK_CLIENT(client); + } return; } status = db_get_field( paddr, - mp->m_type, + pevext->msg.m_type, reply + 1, - mp->m_count, + pevext->msg.m_count, pfl); if (status < 0) { /* @@ -1283,8 +1305,8 @@ db_field_log *pfl * continue to return an exception * on failure */ - send_err(mp, ECA_GETFAIL, client, RECORD_NAME(paddr)); - log_header(mp, 0); + send_err(&pevext->msg, ECA_GETFAIL, client, RECORD_NAME(paddr)); + log_header(&pevext->msg, 0); } else{ /* @@ -1326,7 +1348,8 @@ db_field_log *pfl * force string message size to be the true size rounded to even * boundary */ - if (mp->m_type == DBR_STRING && mp->m_count == 1) { + if (pevext->msg.m_type == DBR_STRING + && pevext->msg.m_count == 1) { /* add 1 so that the string terminator will be shipped */ strcnt = strlen((char *)(reply + 1)) + 1; reply->m_postsize = strcnt; @@ -1340,7 +1363,7 @@ db_field_log *pfl * them up like db requests when the OPI does not keep up. */ if (!eventsRemaining) - cas_send_msg(client,FALSE); + cas_send_msg(client,!pevext->send_lock); if (pevext->send_lock) UNLOCK_CLIENT(client); @@ -1348,6 +1371,66 @@ db_field_log *pfl return; } + +/* + * no_read_access_event() + * + * !! LOCK needs to applied by caller !! + * + * substantial complication introduced here by the need for backwards + * compatibility + */ +LOCAL void no_read_access_event( +struct client *client, +struct event_ext *pevext +) +{ + struct extmsg *reply; + int v41; + + v41 = CA_V41(CA_PROTOCOL_VERSION,client->minor_version_number); + + /* + * continue to return an exception + * on failure to pre v41 clients + */ + if(!v41){ + send_err( + &pevext->msg, + ECA_GETFAIL, + client, + RECORD_NAME(&pevext->pciu->addr)); + return; + } + + reply = (struct extmsg *) ALLOC_MSG(client, pevext->size); + if (!reply) { + send_err( + &pevext->msg, + ECA_TOLARGE, + client, + RECORD_NAME(&pevext->pciu->addr)); + return; + } + else{ + /* + * New clients recv the status of the + * operation directly to the + * event/put/get callback. + * + * Fetched value is zerod in case they + * use it even when the status indicates + * failure. + * + * The m_cid field in the protocol + * header is abused to carry the status + */ + bzero((char *)(reply+1), pevext->size); + reply->m_cid = ECA_NORDACCESS; + END_MSG(client); + } +} + /* * @@ -1388,7 +1471,6 @@ struct extmsg *mp, struct client *client ) { - ELLLIST *addrq = &client->addrq; struct extmsg *search_reply; struct extmsg *get_reply; unsigned short *pMinorVersion; @@ -1454,10 +1536,29 @@ struct client *client LOCK_CLIENT(client); send_err(mp, ECA_ALLOCMEM, client, "No room for security table"); UNLOCK_CLIENT(client); - free(pchannel); + FASTLOCK(&rsrv_free_addrq_lck); + ellAdd(&rsrv_free_addrq, &pchannel->node); + FASTUNLOCK(&rsrv_free_addrq_lck); + return; + } + asPutClientPvt(pchannel->asClientPVT, pchannel); + + /* + * Existing build() interface to the client does not provide mechanism + * to inform them that the channel connected but the value + * couldnt be fetched so search/get combined op + * to no read access channel not allowed. + */ + if (mp->m_cmmd == IOC_BUILD && !asCheckGet(pchannel->asClientPVT)) { + LOCK_CLIENT(client); + send_err(mp, ECA_NORDACCESS, client, RECORD_NAME(&tmp_addr)); + UNLOCK_CLIENT(client); + asRemoveClient(&pchannel->asClientPVT); + FASTLOCK(&rsrv_free_addrq_lck); + ellAdd(&rsrv_free_addrq, &pchannel->node); + FASTUNLOCK(&rsrv_free_addrq_lck); return; } - asRegisterClientCallback(pchannel->asClientPVT, casAccessRightsCB); /* * allocate a server id and enter the channel pointer @@ -1473,7 +1574,9 @@ struct client *client send_err(mp, ECA_ALLOCMEM, client, "No room for hash table"); UNLOCK_CLIENT(client); asRemoveClient(&pchannel->asClientPVT); - free(pchannel); + FASTLOCK(&rsrv_free_addrq_lck); + ellAdd(&rsrv_free_addrq, &pchannel->node); + FASTUNLOCK(&rsrv_free_addrq_lck); return; } @@ -1485,9 +1588,9 @@ struct client *client if (mp->m_cmmd == IOC_BUILD) { - FAST short type = (mp + 1)->m_type; - FAST unsigned int count = (mp + 1)->m_count; - FAST unsigned int size; + short type = (mp + 1)->m_type; + unsigned int count = (mp + 1)->m_count; + unsigned int size; /* * must be large enough to hold both the search and the build-get @@ -1511,16 +1614,24 @@ struct client *client pchannel->sid, pchannel); FASTUNLOCK(&rsrv_free_addrq_lck); - free(pchannel); + FASTLOCK(&rsrv_free_addrq_lck); + ellAdd(&rsrv_free_addrq, &pchannel->node); + FASTUNLOCK(&rsrv_free_addrq_lck); return; } else { struct event_ext evext; - evext.mp = mp + 1; evext.pciu = pchannel; - evext.mp->m_cid = sid; + evext.msg = *(mp+1); + /* + * this allows extra build replies + * to be dicarded + */ + evext.msg.m_cmmd = IOC_READ_BUILD; + evext.msg.m_cid = sid; evext.send_lock = FALSE; evext.size = dbr_size_n(type, count); + evext.pdbev = NULL; evext.get = TRUE; /* @@ -1531,12 +1642,6 @@ struct client *client * is not flushed once each call. */ read_reply(&evext, &tmp_addr, TRUE, NULL); - - /* - * this allows extra build replies - * to be dicarded - */ - get_reply->m_cmmd = IOC_READ_BUILD; } } search_reply = (struct extmsg *) @@ -1563,7 +1668,7 @@ struct client *client END_MSG(client); /* store the addr block on the cast queue until it is claimed */ - ellAdd(addrq, &pchannel->node); + ellAdd(&client->addrq, &pchannel->node); UNLOCK_CLIENT(client); @@ -1781,13 +1886,99 @@ LOCAL struct channel_in_use *MPTOPCIU(struct extmsg *mp) /* * casAccessRightsCB() * + * If access right state changes then inform the client. + * */ LOCAL void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type) { + struct client *pclient; + struct channel_in_use *pciu; + struct extmsg *reply; + struct event_ext *pevext; + int status; + unsigned ar; + int v41; + + pciu = asGetClientPvt(ascpvt); + if(!pciu){ + printf("casAccessRightsCB() without channel pointer ??\n"); + return; + } + pclient = pciu->client; + assert(pclient); + v41 = CA_V41(CA_PROTOCOL_VERSION,pclient->minor_version_number); + switch(type) { case asClientCOAR: + /* + * noop if this is an old client + */ + if(!v41){ + break; + } + + ar = 0; /* none */ + if(asCheckGet(ascpvt)){ + ar |= CA_ACCESS_RIGHT_READ; + } + if(asCheckPut(ascpvt)){ + ar |= CA_ACCESS_RIGHT_WRITE; + } + + LOCK_CLIENT(pclient); + reply = (struct extmsg *)ALLOC_MSG(pclient, 0); + assert(reply); + + *reply = nill_msg; + reply->m_cmmd = IOC_ACCESS_RIGHTS; + reply->m_cid = pciu->cid; + reply->m_available = ar; + + END_MSG(pclient); + + /* + * Update all event call backs + */ + for (pevext = (struct event_ext *) ellFirst(&pciu->eventq); + pevext; + pevext = (struct event_ext *) ellNext(&pevext->node)){ + + if(pevext->pdbev && !(ar&CA_ACCESS_RIGHT_READ)){ + status = db_cancel_event(pevext->pdbev); + assert(status == OK); + pevext->pdbev = NULL; + } + else if(!pevext->pdbev && ar&CA_ACCESS_RIGHT_READ){ + pevext->pdbev = + (struct event_block *)(pevext+1); + + status = db_add_event( + pclient->evuser, + &pciu->addr, + read_reply, + pevext, + pevext->mask, + pevext->pdbev); + if (status == ERROR) { + pevext->pdbev = NULL; + send_err( + &pevext->msg, + ECA_ADDFAIL, + pclient, + RECORD_NAME(&pciu->addr)); + } + } + + if(pevext->pdbev){ + db_post_single_event(pevext->pdbev); + } + } + + UNLOCK_CLIENT(pclient); + break; + default: break; } diff --git a/src/rsrv/caservertask.c b/src/rsrv/caservertask.c index 89195e275..721256037 100644 --- a/src/rsrv/caservertask.c +++ b/src/rsrv/caservertask.c @@ -45,23 +45,24 @@ */ static char *sccsId = "$Id$"; +#include +#include +#include #include -#include #include #include #include #include #include -#include #include #include #include #include -#include #include #include +#include #include #include #include @@ -272,8 +273,14 @@ LOCAL int terminate_one_client(struct client *client) } } - pciu = (struct channel_in_use *) & client->addrq; - while (pciu = (struct channel_in_use *) pciu->node.next){ + while(TRUE){ + LOCK_CLIENT(client); + pciu = (struct channel_in_use *) ellGet(&client->addrq); + UNLOCK_CLIENT(client); + if(!pciu){ + break; + } + /* * put notify in progress needs to be deleted */ @@ -283,19 +290,27 @@ LOCAL int terminate_one_client(struct client *client) } } - while (pevext = (struct event_ext *) ellGet(&pciu->eventq)) { + while (TRUE){ + /* + * AS state change could be using this list + */ + LOCK_CLIENT(client); + pevext = (struct event_ext *) ellGet(&pciu->eventq); + UNLOCK_CLIENT(client); + if(!pevext){ + break; + } - status = db_cancel_event( - (struct event_block *)(pevext + 1)); - if (status) - taskSuspend(0); + if(pevext->pdbev){ + status = db_cancel_event(pevext->pdbev); + assert(status == OK); + } FASTLOCK(&rsrv_free_eventq_lck); ellAdd(&rsrv_free_eventq, &pevext->node); FASTUNLOCK(&rsrv_free_eventq_lck); } status = db_flush_extra_labor_event(client->evuser); - if (status) - taskSuspend(0); + assert(status==OK); if(pciu->pPutNotify){ free(pciu->pPutNotify); } @@ -322,6 +337,14 @@ LOCAL int terminate_one_client(struct client *client) NULL, NULL); } + + /* + * place per channel block onto the + * free list + */ + FASTLOCK(&rsrv_free_addrq_lck); + ellAdd(&rsrv_free_addrq, &pciu->node); + FASTUNLOCK(&rsrv_free_addrq_lck); } if (client->evuser) { @@ -338,13 +361,6 @@ LOCAL int terminate_one_client(struct client *client) NULL, NULL); - /* free dbaddr str */ - FASTLOCK(&rsrv_free_addrq_lck); - ellConcat( - &rsrv_free_addrq, - &client->addrq); - FASTUNLOCK(&rsrv_free_addrq_lck); - if(FASTLOCKFREE(&client->putNotifyLock)<0){ logMsg("CAS: couldnt free sem\n", NULL, @@ -448,6 +464,7 @@ int client_stat(void) */ LOCAL void log_one_client(struct client *client) { + int i; struct channel_in_use *pciu; struct sockaddr_in *psaddr; char *pproto; @@ -487,6 +504,7 @@ LOCAL void log_one_client(struct client *client) bytes_reserved = 0; bytes_reserved += sizeof(struct client); + LOCK_CLIENT(client); pciu = (struct channel_in_use *) client->addrq.node.next; while (pciu){ bytes_reserved += sizeof(struct channel_in_use); @@ -499,6 +517,7 @@ LOCAL void log_one_client(struct client *client) } pciu = (struct channel_in_use *) ellNext(&pciu->node); } + UNLOCK_CLIENT(client); psaddr = &client->addr; printf("\tRemote address %u.%u.%u.%u Remote port %d state=%s\n", @@ -511,13 +530,21 @@ LOCAL void log_one_client(struct client *client) printf( "\tChannel count %d\n", ellCount(&client->addrq)); printf( "\t%d bytes allocated\n", bytes_reserved); + LOCK_CLIENT(client); pciu = (struct channel_in_use *) client->addrq.node.next; + i=0; while (pciu){ - printf( "\t%s(%d) ", + printf( "\t%s(%d%c%c)", pciu->addr.precord, - pciu->eventq.count); + ellCount(&pciu->eventq), + asCheckGet(pciu->asClientPVT)?'r':'-', + asCheckPut(pciu->asClientPVT)?'w':'-'); pciu = (struct channel_in_use *) ellNext(&pciu->node); + if( ++i % 3 == 0){ + printf("\n"); + } } + UNLOCK_CLIENT(client); printf("\n"); diff --git a/src/rsrv/cast_server.c b/src/rsrv/cast_server.c index 561e90969..a931f37df 100644 --- a/src/rsrv/cast_server.c +++ b/src/rsrv/cast_server.c @@ -56,7 +56,7 @@ * pend which could lock up the cast server. */ -static char *sccsId = "@(#)cast_server.c 1.17\t8/5/93"; +static char *sccsId = "$Id$"; #include #include @@ -253,7 +253,7 @@ int cast_server(void) } if(CASDEBUG>2) - count = prsrv_cast_client->addrq.count; + count = ellCount(&prsrv_cast_client->addrq); status = camessage( prsrv_cast_client, @@ -273,11 +273,12 @@ int cast_server(void) } } - if(prsrv_cast_client->addrq.count){ - if(CASDEBUG>2){ + if(CASDEBUG>2){ + if(ellCount(&prsrv_cast_client->addrq)){ logMsg( "CAS: Fnd %d name matches (%d tot)\n", - prsrv_cast_client->addrq.count-count, - prsrv_cast_client->addrq.count, + ellCount(&prsrv_cast_client->addrq) + -count, + ellCount(&prsrv_cast_client->addrq), NULL, NULL, NULL, diff --git a/src/rsrv/server.h b/src/rsrv/server.h index 0e4cb6c5d..1de255e13 100644 --- a/src/rsrv/server.h +++ b/src/rsrv/server.h @@ -125,9 +125,10 @@ struct channel_in_use{ struct event_ext{ ELLNODE node; struct extmsg msg; -struct extmsg *mp; /* for speed (IOC_READ) */ struct channel_in_use *pciu; +struct event_block *pdbev; /* ptr to db event block */ unsigned size; /* for speed */ +unsigned mask; char modified; /* mod & ev flw ctrl enbl */ char send_lock; /* lock send buffer */ char get; /* T: get F: monitor */ @@ -157,10 +158,14 @@ GLBLTYPE struct client *prsrv_cast_client; GLBLTYPE BUCKET *pCaBucket; #define LOCK_CLIENT(CLIENT)\ -FASTLOCK(&(CLIENT)->lock); +{\ +FASTLOCK(&(CLIENT)->lock);\ +} #define UNLOCK_CLIENT(CLIENT)\ -FASTUNLOCK(&(CLIENT)->lock); +{ \ +FASTUNLOCK(&(CLIENT)->lock);\ +} #define EXTMSGPTR(CLIENT)\ ((struct extmsg *) &(CLIENT)->send.buf[(CLIENT)->send.stk]) @@ -177,9 +182,9 @@ FASTUNLOCK(&(CLIENT)->lock); (CLIENT)->send.stk += sizeof(struct extmsg) + EXTMSGPTR(CLIENT)->m_postsize -#define LOCK_CLIENTQ FASTLOCK(&clientQlock) +#define LOCK_CLIENTQ FASTLOCK(&clientQlock); -#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock) +#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock); struct client *existing_client(); int camsgtask();