added new EPICS env var

fixed delete of cast iiu when all disconn chan deleted
This commit is contained in:
Jeff Hill
1994-11-29 22:40:22 +00:00
parent d32a6bb770
commit 81de80789c
9 changed files with 262 additions and 136 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ LIBOBJS = \
LIBNAME = libca.a
PROD = caRepeater acctst
PROD = caRepeater
include $(EPICS)/config/RULES.Unix
+2 -3
View File
@@ -11,10 +11,9 @@ SRCS.c = \
OBJS = \
iocinf.o access.o test_event.o service.o flow_control.o \
repeater.o conn.o syncgrp.o if_depen.o bsd_depen.o vxWorks_depen.o \
acctst.o
repeater.o conn.o syncgrp.o if_depen.o bsd_depen.o vxWorks_depen.o
PROD = caLib acctst.o
PROD = caLib
include $(EPICS)/config/RULES.Vx
+44 -12
View File
@@ -481,7 +481,8 @@ int APIENTRY ca_task_initialize(void)
*/
int ca_os_independent_init (void)
{
unsigned sec;
unsigned sec;
long status;
ca_static->ca_exception_func = ca_default_exception_handler;
ca_static->ca_exception_arg = NULL;
@@ -531,6 +532,27 @@ int ca_os_independent_init (void)
bucketCreate(CLIENT_HASH_TBL_SIZE);
assert(ca_static->ca_pFastBucket);
status = envGetDoubleConfigParam (
&EPICS_CA_CONN_TMO,
&ca_static->ca_connectTMO);
if (status) {
ca_static->ca_connectTMO =
CA_CONN_VERIFY_PERIOD;
ca_printf (
"EPICS \"%s\" float fetch failed\n",
EPICS_CA_CONN_TMO.name);
ca_printf (
"Setting \"%s\" = %f\n",
EPICS_CA_CONN_TMO.name,
ca_static->ca_connectTMO);
}
ca_static->ca_repeater_port =
caFetchPortConfig(&EPICS_CA_REPEATER_PORT, CA_REPEATER_PORT);
ca_static->ca_server_port =
caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT);
if (repeater_installed()==FALSE) {
ca_spawn_repeater();
}
@@ -2539,7 +2561,7 @@ void clearChannelResources(unsigned id)
ca_static->ca_pSlowBucket, &chix->cid);
assert (status == BUCKET_SUCCESS);
free (chix);
if (!piiu->chidlist.count){
if (piiu!=piiuCast && !piiu->chidlist.count){
TAG_CONN_DOWN(piiu);
}
@@ -2911,20 +2933,30 @@ void ca_ready_message(struct ioc_in_use *piiu)
* echo_request (lock must be on)
*
*/
void echo_request(struct ioc_in_use *piiu)
int echo_request(struct ioc_in_use *piiu, ca_time *pCurrentTime)
{
struct extmsg hdr;
int status;
struct extmsg *phdr;
hdr.m_cmmd = htons(IOC_ECHO);
hdr.m_type = htons(0);
hdr.m_count = htons(0);
hdr.m_cid = htons(0);
hdr.m_available = htons(0);
hdr.m_postsize = 0;
status = cac_alloc_msg_no_flush (piiu, sizeof(*phdr), &phdr);
if (status) {
return status;
}
phdr->m_cmmd = htons(IOC_ECHO);
phdr->m_type = htons(0);
phdr->m_count = htons(0);
phdr->m_cid = htons(0);
phdr->m_available = htons(0);
phdr->m_postsize = 0;
CAC_ADD_MSG(piiu);
cac_push_msg(piiu, &hdr, NULL);
piiu->echoPending = TRUE;
piiu->send_needed = TRUE;
piiu->timeAtEchoRequest = *pCurrentTime;
return ECA_NORMAL;
}
+12 -19
View File
@@ -90,7 +90,7 @@ void manage_conn(int silent)
piiu;
piiu = (IIU *) piiu->node.next){
if(piiu == piiuCast || !piiu->conn_up){
if (piiu == piiuCast || !piiu->conn_up) {
continue;
}
@@ -98,11 +98,11 @@ void manage_conn(int silent)
* mark connection for shutdown if outgoing messages
* are not accepted by TCP/IP for several seconds
*/
if(piiu->sendPending){
if (piiu->sendPending) {
delay = cac_time_diff (
&current,
&piiu->timeAtSendBlock);
if(delay > CA_CONN_VERIFY_PERIOD){
if (delay>ca_static->ca_connectTMO) {
TAG_CONN_DOWN(piiu);
continue;
}
@@ -143,18 +143,11 @@ void manage_conn(int silent)
}
}
else{
int sendBytesAvailable;
sendBytesAvailable =
cacRingBufferWriteSize(&piiu->send, TRUE);
delay = cac_time_diff (
&current,
&piiu->timeAtLastRecv);
if(delay>CA_CONN_VERIFY_PERIOD &&
sendBytesAvailable>sizeof(struct extmsg)){
piiu->echoPending = TRUE;
piiu->timeAtEchoRequest = current;
echo_request(piiu);
if (delay>ca_static->ca_connectTMO) {
echo_request(piiu, &current);
}
}
@@ -594,29 +587,29 @@ bhe *lookupBeaconInetAddr(struct in_addr *pnet_addr)
*
* LOCK must be applied
*/
void removeBeaconInetAddr(struct in_addr *pnet_addr)
void removeBeaconInetAddr (struct in_addr *pnet_addr)
{
bhe *pBHE;
bhe **ppBHE;
unsigned index;
index = ntohl(pnet_addr->s_addr);
index = ntohl (pnet_addr->s_addr);
index &= BHT_INET_ADDR_MASK;
assert(index<NELEMENTS(ca_static->ca_beaconHash));
assert (index<NELEMENTS(ca_static->ca_beaconHash));
ppBHE = &ca_static->ca_beaconHash[index];
pBHE = *ppBHE;
while(pBHE){
if(pBHE->inetAddr.s_addr == pnet_addr->s_addr){
while (pBHE) {
if (pBHE->inetAddr.s_addr == pnet_addr->s_addr) {
*ppBHE = pBHE->pNext;
free(pBHE);
free (pBHE);
return;
}
ppBHE = &pBHE->pNext;
pBHE = *ppBHE;
}
assert(0);
assert (0);
}
+171 -93
View File
@@ -190,7 +190,8 @@ int net_proto
}
pNode->destAddr.inetAddr.sin_family = AF_INET;
pNode->destAddr.inetAddr.sin_addr = *pnet_addr;
pNode->destAddr.inetAddr.sin_port = htons(CA_SERVER_PORT);
pNode->destAddr.inetAddr.sin_port =
htons (ca_static->ca_server_port);
ellAdd(&piiu->destAddr, &pNode->node);
piiu->recvBytes = tcp_recv_msg;
piiu->sendBytes = cac_tcp_send_msg_piiu;
@@ -426,21 +427,13 @@ int net_proto
}
/*
* LOCK is for piiu->destAddr list
* (lock outside because this is used by the server also)
* load user and auto configured
* broadcast address list
*/
LOCK;
caDiscoverInterfaces(
&piiu->destAddr,
sock,
CA_SERVER_PORT);
UNLOCK;
caAddConfiguredAddr(
caSetupBCastAddrList(
&piiu->destAddr,
&EPICS_CA_ADDR_LIST,
sock,
CA_SERVER_PORT);
sock,
ca_static->ca_server_port);
cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf));
cacRingBufferInit(&piiu->send, min(MAX_UDP,
@@ -482,6 +475,58 @@ int net_proto
return ECA_NORMAL;
}
/*
* caSetupBCastAddrList()
*/
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port)
{
char *pstr;
ENV_PARAM yesno;
int yes;
/*
* dont load the list twice
*/
assert (ellCount(pList)==0);
/*
* Check to see if the user has disabled
* initializing the search b-cast list
* from the interfaces found.
*/
yes = TRUE;
pstr = envGetConfigParam (
&EPICS_CA_AUTO_ADDR_LIST,
sizeof(yesno.dflt),
yesno.dflt);
if (pstr) {
if (strstr(pstr,"no")||strstr(pstr,"NO")) {
yes = FALSE;
}
}
/*
* LOCK is for piiu->destAddr list
* (lock outside because this is used by the server also)
*/
if (yes) {
caDiscoverInterfaces(
pList,
sock,
port);
}
caAddConfiguredAddr(
pList,
&EPICS_CA_ADDR_LIST,
sock,
port);
if (ellCount(pList)==0) {
ca_signal (ECA_NOSEARCHADDR, NULL);
}
}
/*
@@ -529,7 +574,7 @@ void notify_ca_repeater()
memset((char *)&msg, 0, sizeof(msg));
msg.m_cmmd = htons(REPEATER_REGISTER);
msg.m_available = saddr.sin_addr.s_addr;
saddr.sin_port = htons(CA_CLIENT_PORT);
saddr.sin_port = htons(ca_static->ca_repeater_port);
/*
* Intentionally sending a zero length message here
* until most CA repeater daemons have been restarted
@@ -1097,116 +1142,116 @@ void close_ioc (struct ioc_in_use *piiu)
/*
* dont close twice
*/
if(piiu->sock_chan == INVALID_SOCKET){
return;
}
assert (piiu->sock_chan!=INVALID_SOCKET);
LOCK;
ellDelete(&iiuList, &piiu->node);
ellDelete (&iiuList, &piiu->node);
/*
* attempt to clear out messages in recv queue
*/
(*piiu->procInput)(piiu);
(*piiu->procInput) (piiu);
if(piiu == piiuCast){
if (piiu == piiuCast) {
piiuCast = NULL;
}
/*
* Mark all of their channels disconnected
* prior to calling handlers incase the
* handler tries to use a channel before
* I mark it disconnected.
*/
chix = (chid) &piiu->chidlist.node.next;
while(chix = (chid) chix->node.next){
chix->type = TYPENOTCONN;
chix->count = 0;
chix->state = cs_prev_conn;
chix->id.sid = ~0L;
chix->ar.read_access = FALSE;
chix->ar.write_access = FALSE;
else {
/*
* try to reconnect
* remove IOC from the hash table
*/
chix->retry = 0;
}
pNode = (caAddrNode *) piiu->destAddr.node.next;
assert (pNode);
removeBeaconInetAddr (&pNode->destAddr.inetAddr.sin_addr);
/*
* Mark all of their channels disconnected
* prior to calling handlers incase the
* handler tries to use a channel before
* I mark it disconnected.
*/
chix = (chid) &piiu->chidlist.node.next;
while (chix = (chid) chix->node.next) {
chix->type = TYPENOTCONN;
chix->count = 0;
chix->state = cs_prev_conn;
chix->id.sid = ~0L;
chix->ar.read_access = FALSE;
chix->ar.write_access = FALSE;
/*
* try to reconnect
*/
chix->retry = 0;
}
if (piiu->chidlist.count) {
ca_signal (ECA_DISCONN,piiu->host_name_str);
}
/*
* call their connection handler as required
*/
chix = (chid) &piiu->chidlist.node.next;
while (chix = (chid) chix->node.next) {
LOCKEVENTS;
if (chix->pConnFunc) {
struct connection_handler_args args;
args.chid = chix;
args.op = CA_OP_CONN_DOWN;
(*chix->pConnFunc) (args);
}
if (chix->pAccessRightsFunc) {
struct access_rights_handler_args args;
args.chid = chix;
args.ar = chix->ar;
(*chix->pAccessRightsFunc) (args);
}
UNLOCKEVENTS;
chix->piiu = piiuCast;
}
/*
* move all channels to the broadcast IIU
*
* if we loose the broadcast IIU its a severe error
*/
assert (piiuCast);
ellConcat (&piiuCast->chidlist, &piiu->chidlist);
assert (piiu->chidlist.count==0);
}
/*
* Try to reconnect
*/
ca_static->ca_search_retry = 0;
if(piiu->chidlist.count){
ca_signal(ECA_DISCONN,piiu->host_name_str);
}
/*
* remove IOC from the hash table
*/
pNode = (caAddrNode *) piiu->destAddr.node.next;
assert(pNode);
removeBeaconInetAddr(&pNode->destAddr.inetAddr.sin_addr);
/*
* call their connection handler as required
*/
chix = (chid) &piiu->chidlist.node.next;
while(chix = (chid) chix->node.next){
if (fd_register_func) {
LOCKEVENTS;
if(chix->pConnFunc){
struct connection_handler_args args;
args.chid = chix;
args.op = CA_OP_CONN_DOWN;
(*chix->pConnFunc)(args);
}
if(chix->pAccessRightsFunc){
struct access_rights_handler_args args;
args.chid = chix;
args.ar = chix->ar;
(*chix->pAccessRightsFunc)(args);
}
UNLOCKEVENTS;
chix->piiu = piiuCast;
}
/*
* move all channels to the broadcast IIU
*
* if we loose the broadcast IIU its a severe error
*/
assert(piiuCast);
ellConcat(&piiuCast->chidlist, &piiu->chidlist);
assert(piiu->chidlist.count==0);
if(fd_register_func){
LOCKEVENTS;
(*fd_register_func)(fd_register_arg, piiu->sock_chan, FALSE);
(*fd_register_func) (fd_register_arg, piiu->sock_chan, FALSE);
UNLOCKEVENTS;
}
status = socket_close(piiu->sock_chan);
assert(status == 0);
status = socket_close (piiu->sock_chan);
assert (status == 0);
/*
* free message body cache
*/
if(piiu->pCurData){
free(piiu->pCurData);
if (piiu->pCurData) {
free (piiu->pCurData);
piiu->pCurData = NULL;
piiu->curDataMax = 0;
}
piiu->sock_chan = INVALID_SOCKET;
ellFree(&piiu->destAddr);
ellFree (&piiu->destAddr);
free (piiu);
free(piiu);
UNLOCK;
}
@@ -1258,7 +1303,7 @@ int repeater_installed()
memset((char *)&bd,0,sizeof bd);
bd.sin_family = AF_INET;
bd.sin_addr.s_addr = INADDR_ANY;
bd.sin_port = htons(CA_CLIENT_PORT);
bd.sin_port = htons(ca_static->ca_repeater_port);
status = bind( sock,
(struct sockaddr *) &bd,
sizeof bd);
@@ -1605,3 +1650,36 @@ void caPrintAddrList(ELLLIST *pList)
}
}
/*
* caFetchPortConfig()
*/
unsigned caFetchPortConfig(ENV_PARAM *pEnv, unsigned defaultPort)
{
long longStatus;
long port;
longStatus = envGetLongConfigParam(pEnv, &port);
if (longStatus!=0) {
port = defaultPort;
ca_printf ("EPICS \"%s\" integer fetch failed\n", pEnv->name);
ca_printf ("setting \"%s\" = %ld\n", pEnv->name, port);
}
/*
* Thus must be a server port that will fit in a signed
* short
*/
if (port <= IPPORT_USERRESERVED || port>SHRT_MAX) {
ca_printf ("EPICS \"%s\" out of range\n", pEnv->name);
/*
* Quit if the port is wrong due CA coding error
*/
assert (port != defaultPort);
port = defaultPort;
ca_printf ("Setting \"%s\" = %ld\n", pEnv->name, port);
}
return port;
}
+13 -4
View File
@@ -84,6 +84,7 @@ HDRVERSIONID(iocinfh, "$Id$")
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
/*
@@ -198,9 +199,12 @@ extern const ca_time CA_CURRENT_TIME;
* long we will wait for an echo reply before we
* give up and flag the connection for disconnect
* - CA_ECHO_TIMEOUT.
*
* CA_CONN_VERIFY_PERIOD is normally obtained from an
* EPICS environment variable.
*/
#define CA_ECHO_TIMEOUT 5 /* (sec) disconn if no echo reply tmo */
#define CA_CONN_VERIFY_PERIOD 30 /* (sec) how often to request echo */
#define CA_ECHO_TIMEOUT 5.0 /* (sec) disconn no echo reply tmo */
#define CA_CONN_VERIFY_PERIOD 30.0 /* (sec) how often to request echo */
/*
* only used when communicating with old servers
@@ -208,7 +212,7 @@ extern const ca_time CA_CURRENT_TIME;
#define CA_RETRY_PERIOD 5 /* int sec to next keepalive */
#define N_REPEATER_TRIES_PRIOR_TO_MSG 50
#define REPEATER_TRY_PERIOD (0.1)
#define REPEATER_TRY_PERIOD (0.1)
#ifdef vxWorks
typedef struct caclient_put_notify{
@@ -396,6 +400,7 @@ struct ca_static{
ca_time ca_conn_next_retry;
ca_time ca_conn_retry_delay;
ca_time ca_last_repeater_try;
ca_real ca_connectTMO;
long ca_pndrecvcnt;
unsigned long ca_nextSlowBucketId;
unsigned long ca_nextFastBucketId;
@@ -416,6 +421,8 @@ struct ca_static{
bhe *ca_beaconHash[BHT_INET_ADDR_MASK+1];
unsigned ca_repeater_tries;
unsigned ca_search_retry; /* search retry seq number */
unsigned short ca_server_port;
unsigned short ca_repeater_port;
char ca_sprintf_buf[256];
unsigned ca_post_msg_active:1;
unsigned ca_manage_conn_active:1;
@@ -494,7 +501,7 @@ int ca_request_event(evid monix);
void ca_busy_message(struct ioc_in_use *piiu);
void ca_ready_message(struct ioc_in_use *piiu);
void noop_msg(struct ioc_in_use *piiu);
void echo_request(struct ioc_in_use *piiu);
int echo_request(struct ioc_in_use *piiu, ca_time *pCurrentTime);
void issue_claim_channel(struct ioc_in_use *piiu, chid pchan);
void issue_identify_client(struct ioc_in_use *piiu);
void issue_client_host_name(struct ioc_in_use *piiu);
@@ -555,6 +562,8 @@ int net_proto
int ca_check_for_fp(void);
void caSetupBCastAddrList (ELLLIST *pList, SOCKET sock, unsigned port);
int ca_os_independent_init (void);
void freeBeaconHash(struct ca_static *ca_temp);
+7 -1
View File
@@ -50,9 +50,15 @@ HDRVERSIONID(iocmsgh, "@(#) $Id$ CA version 4.4")
#define CA_V44(MAJOR,MINOR) ( 0 )
#endif
/*
* NOTE: These port numbers are only used if the CA repeater and
* CA server port numbers cant be obtained from the EPICS
* environment variables "EPICS_CA_REPEATER_PORT" and
* "EPICS_CA_SERVER_PORT"
*/
#define CA_PORT_BASE IPPORT_USERRESERVED + 56
#define CA_SERVER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2)
#define CA_CLIENT_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2+1)
#define CA_REPEATER_PORT (CA_PORT_BASE+CA_PROTOCOL_VERSION*2+1)
#define MAX_UDP 1024
#define MAX_TCP (MAX_UDP*16) /* so waveforms fit */
+6 -1
View File
@@ -100,6 +100,11 @@ void ca_repeater()
int from_size = sizeof from;
struct one_client *pclient;
struct one_client *pnxtclient;
short port;
port = caFetchPortConfig(
&EPICS_CA_REPEATER_PORT,
CA_REPEATER_PORT);
ellInit(&client_list);
@@ -113,7 +118,7 @@ void ca_repeater()
memset((char *)&bd, 0, sizeof(bd));
bd.sin_family = AF_INET;
bd.sin_addr.s_addr = INADDR_ANY;
bd.sin_port = htons(CA_CLIENT_PORT);
bd.sin_port = htons(port);
status = bind(sock, (struct sockaddr *)&bd, sizeof(bd));
if(status<0){
if(MYERRNO != EADDRINUSE){
+6 -2
View File
@@ -419,7 +419,7 @@ LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
/*
* stop the socket recv task
* (only after we get the LOCK here)
* !! only after we get the LOCK here !!
*/
if (taskIdVerify (pcas->recv_tid)==OK) {
taskwdRemove (pcas->recv_tid);
@@ -439,7 +439,11 @@ LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
/*
* Cancel all local events
* (and put call backs)
*
* !! temp release lock so that the event task
* can finish !!
*/
UNLOCK;
chix = (chid) & pcas->ca_local_chidlist.node;
while (chix = (chid) chix->node.next) {
while (monix = (evid) ellGet(&chix->eventq)) {
@@ -457,7 +461,7 @@ LOCAL int cac_os_depen_exit_tid (struct ca_static *pcas, int tid)
free (ppn);
}
}
LOCK;
/*
* set ca_static for access.c