From 2294913a54d87f15ed840b2eb23555405e4cc80c Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Wed, 30 Mar 1994 11:29:35 +0000 Subject: [PATCH] added access control and ring buffers --- src/ca/access.c | 1935 +++++++++++++++++++++++++++++------------ src/ca/acctst.c | 370 ++++++-- src/ca/ca_printf.c | 14 +- src/ca/conn.c | 27 +- src/ca/convert.c | 1819 +++++++++++++++++++++++++++----------- src/ca/flow_control.c | 9 +- src/ca/iocinf.c | 1469 ++++++++++++++++++------------- src/ca/iocinf.h | 250 ++++-- src/ca/iocmsg.h | 20 +- src/ca/net_convert.h | 298 +++---- src/ca/os_depen.h | 18 +- src/ca/repeater.c | 20 +- src/ca/service.c | 1028 ++++++++++++---------- src/ca/syncgrp.c | 53 +- src/ca/test_event.c | 6 + 15 files changed, 4819 insertions(+), 2517 deletions(-) diff --git a/src/ca/access.c b/src/ca/access.c index 930443a3b..88c435d73 100644 --- a/src/ca/access.c +++ b/src/ca/access.c @@ -90,6 +90,8 @@ /* 120293 joh flush in ca_pend_io() if no IO oustanding */ /* 121693 joh fixed bucketLib level memory leak */ /* 011394 joh fixed bucketLib level memory leak (vxWorks) */ +/* 020494 joh Added user name protocol */ +/* 022294 joh fixed recv task id verify at exit (vxWorks) */ /* */ /*_begin */ /************************************************************************/ @@ -114,7 +116,7 @@ /************************************************************************/ /*_end */ -static char *sccsId = "@(#)access.c 1.45 1/14/94"; +static char *sccsId = "$Id$"; /* * allocate error message string array @@ -122,47 +124,46 @@ static char *sccsId = "@(#)access.c 1.45 1/14/94"; */ #define CA_ERROR_GLBLSOURCE -#if defined(VMS) -# include stsdef.h -# include ssdef.h -# include psldef.h -# include prcdef.h -# include descrip.h -#else -# if defined(UNIX) -# else -# if defined(vxWorks) +#include +#include +#include + +#ifdef VMS +# include +# include +# include +# include +# include +#endif /*VMS*/ + +#ifdef UNIX +# include +#endif /*UNIX*/ + +#ifdef vxWorks # include # include # include # include -# include # include # include # include # include # include # include -# include -# include # include -# else - @@@@ dont compile @@@@ -# endif -# endif -#endif +#endif /*vxWorks*/ /* * allocate db_access message strings here */ #define DB_TEXT_GLBLSOURCE -#include -#include #include #include + #ifdef vxWorks #include -#endif +#endif /*vxWorks*/ /* * logistical problems prevent including this file @@ -179,21 +180,21 @@ static char *sccsId = "@(#)access.c 1.45 1/14/94"; /* Macros for syncing message insertion into send buffer */ /****************************************************************/ #define EXTMSGPTR(PIIU)\ - ((struct extmsg *) &(PIIU)->send->buf[(PIIU)->send->stk]) + ((struct extmsg *) &(PIIU)->send.buf[(PIIU)->send.wtix]) + +#define CAC_ALLOC_MSG(PIIU, EXTSIZE, PPTR) cac_alloc_msg((PIIU), (EXTSIZE), (PPTR)) -#define CAC_ALLOC_MSG(PIIU, EXTSIZE) cac_alloc_msg((PIIU), (EXTSIZE)) /* - * Make sure string is aligned for the most restrictive architecture - * VAX none required - * 680xx binary rounding - * SPARC octal rounding + * Performs worst case message alignment */ #define CAC_ADD_MSG(PIIU) \ { \ + unsigned long size; \ struct extmsg *mp = EXTMSGPTR(PIIU); \ - mp->m_postsize = CA_MESSAGE_ALIGN(mp->m_postsize); \ - (PIIU)->send->stk += sizeof(struct extmsg) + mp->m_postsize; \ + size = mp->m_postsize = CA_MESSAGE_ALIGN(mp->m_postsize); \ mp->m_postsize = htons(mp->m_postsize); \ + CAC_RING_BUFFER_WRITE_ADVANCE( \ + &(PIIU)->send, sizeof(struct extmsg) + size); \ } @@ -225,15 +226,6 @@ static char *sccsId = "@(#)access.c 1.45 1/14/94"; } \ } -#define INITCHK \ -if(!ca_static){ \ - int s; \ - s = ca_task_initialize(); \ - if(s != ECA_NORMAL){ \ - return s; \ - } \ -} - static struct extmsg nullmsg; /* @@ -241,9 +233,10 @@ static struct extmsg nullmsg; */ #ifdef __STDC__ -LOCAL struct extmsg *cac_alloc_msg( +LOCAL int cac_alloc_msg( struct ioc_in_use *piiu, -unsigned extsize +unsigned extsize, +struct extmsg **ppMsg ); LOCAL void spawn_repeater(); LOCAL int check_for_fp(); @@ -251,10 +244,10 @@ LOCAL int ca_add_task_variable(struct ca_static *ca_temp); #ifdef vxWorks LOCAL void ca_task_exit_tcb(WIND_TCB *ptcb); LOCAL void ca_task_exit_tid(int tid); -#else -void ca_process_exit(); -#endif -LOCAL void issue_get_callback(evid monix); +#else /*vxWorks*/ +LOCAL void ca_process_exit(); +#endif /*vxWorks*/ +LOCAL int issue_get_callback(evid monix); LOCAL void ca_event_handler( evid monix, struct db_addr *paddr, @@ -262,28 +255,181 @@ int hold, void *pfl ); LOCAL void ca_pend_io_cleanup(); -void create_udp_fd(); +LOCAL void create_udp_fd(); +static int issue_ca_array_put +( +unsigned cmd, +unsigned long avail, +chtype type, +unsigned long count, +chid chix, +void *pvalue +); +LOCAL void ca_put_notify_action(PUTNOTIFY *ppn); +LOCAL void ca_extra_event_labor(void *pArg); +LOCAL void ca_default_exception_handler(struct exception_handler_args args); -#else +LOCAL int cac_push_msg( +struct ioc_in_use *piiu, +struct extmsg *pmsg, +void *pext +); -LOCAL struct extmsg *cac_alloc_msg(); +LOCAL void cac_wait_for_flush(IIU *piiu); + +#else /*__STDC__*/ + +LOCAL int cac_alloc_msg(); LOCAL void spawn_repeater(); LOCAL int check_for_fp(); LOCAL int ca_add_task_variable(); #ifdef vxWorks LOCAL void ca_task_exit_tcb(); -LOCAL void ca_task_exit_tid(); +LOCAL void ca_task_exit_tid(); #else -void ca_process_exit(); +LOCAL void ca_process_exit(); #endif LOCAL void issue_get_callback(); LOCAL void ca_event_handler(); LOCAL void ca_pend_io_cleanup(); -void ca_default_exception_handler(); -void create_udp_fd(); +LOCAL void ca_default_exception_handler(); +LOCAL void create_udp_fd(); +LOCAL int issue_ca_array_put(); +LOCAL void ca_put_notify_action(); +LOCAL void ca_extra_event_labor(); +LOCAL int cac_push_msg(); +LOCAL void cac_wait_for_flush(); +#endif /*__STDC__*/ + + +/* + * + * cac_push_msg() + * + * return a pointer to reserved message buffer space or + * nill if the message will not fit + * + */ +#ifdef __STDC__ +LOCAL int cac_push_msg( +struct ioc_in_use *piiu, +struct extmsg *pmsg, +void *pext +) +#else +LOCAL int cac_push_msg(piiu, pmsg, pext) +struct ioc_in_use *piiu; +struct extmsg *pmsg; +void *pext; #endif +{ + struct extmsg msg; + unsigned long bytesAvailable; + unsigned long extsize; + unsigned long bytesSent; + + msg = *pmsg; + extsize = CA_MESSAGE_ALIGN(pmsg->m_postsize); + msg.m_postsize = htons(extsize); + + + LOCK; + + /* + * Force contiguous header and body + * + * o Forces hdr and bdy into the same frame if UDP + * + * o Does not allow interleaved messages + * caused by removing recv backlog during + * send under UNIX. + * + * o Does not allow for messages larger than the + * ring buffer size. + */ + if(extsize+sizeof(msg)>piiu->send.max_msg){ + return ECA_TOLARGE; + } + while(TRUE){ + bytesAvailable = + cacRingBufferWriteSize(&piiu->send, FALSE); + if(bytesAvailable>=extsize+sizeof(msg)){ + break; + } + /* + * if connection drops request + * cant be completed + */ + if(!piiu->conn_up){ + UNLOCK; + return ECA_BADCHID; + } + UNLOCK; + cac_wait_for_flush(piiu); + LOCK; + } + + + /* + * push the header onto the ring + */ + bytesSent = cacRingBufferWrite( + &piiu->send, + &msg, + sizeof(msg)); + assert(bytesSent == sizeof(msg)); + + /* + * push message body onto the ring + * + * (optionally encode in netrwork format as we send) + */ + bytesSent = cacRingBufferWrite( + &piiu->send, + pext, + extsize); + assert(bytesSent == extsize); + + UNLOCK; + + return ECA_NORMAL; +} + + +/* + * cac_wait_for_flush() + * + */ +#ifdef __STDC__ +LOCAL void cac_wait_for_flush(IIU *piiu) +#else /*__STDC__*/ +LOCAL void cac_wait_for_flush(piiu) +IIU *piiu; +#endif /*__STDC__*/ +{ + +#ifdef UNIX + { + int flags; + struct timeval itimeout; + + flags = CA_DO_RECVS | CA_DO_SENDS; + + itimeout.tv_usec = LOCALTICKS; + itimeout.tv_sec = 0; + if(post_msg_active){ + ca_select_io(&itimeout, flags); + } + else{ + ca_mux_io(&itimeout, flags); + } + } +#else /*UNIX*/ + (*piiu->sendBytes)(piiu); +#endif /*UNIX*/ +} /* @@ -297,68 +443,71 @@ void create_udp_fd(); * */ #ifdef __STDC__ -LOCAL struct extmsg *cac_alloc_msg( +LOCAL int cac_alloc_msg( struct ioc_in_use *piiu, -unsigned extsize +unsigned extsize, +struct extmsg **ppMsg ) #else -LOCAL struct extmsg *cac_alloc_msg(piiu, extsize) +LOCAL int cac_alloc_msg(piiu, extsize, ppMsg) struct ioc_in_use *piiu; unsigned extsize; +struct extmsg **ppMsg; #endif { unsigned msgsize; - unsigned msglimit; + unsigned long bytesAvailable; struct extmsg *pmsg; msgsize = sizeof(struct extmsg)+extsize; /* - * dont allow client to send enough messages to - * to get into a deadlock + * fail if max message size exceeded */ - if(piiu->outstanding_ack_count > ((unsigned)0) && !post_msg_active){ - unsigned max1; - unsigned size; - - size = piiu->tcp_send_buff_size; - if(RECV_ACTIVE(piiu)){ - max1=size<<2; - } - else{ - max1=size<<1; - } - - if(piiu->bytes_pushing_an_ack > max1){ - if(RECV_ACTIVE(piiu)){ - return NULL; - } - - while(piiu->outstanding_ack_count>0){ - cac_send_msg(); - UNLOCK; - TCPDELAY; - LOCK; - } - } - piiu->bytes_pushing_an_ack += msgsize; + if(msgsize>=piiu->send.max_msg){ + return ECA_TOLARGE; } - msglimit = piiu->max_msg - msgsize; - if(piiu->send->stk > msglimit){ - cac_send_msg(); - if(piiu->send->stk > msglimit){ - if(piiu->outstanding_ack_count > 0){ - piiu->bytes_pushing_an_ack -= msgsize; + bytesAvailable = cacRingBufferWriteSize(&piiu->send, TRUE); + while(bytesAvailablesendBytes)(piiu); +#endif /*UNIX*/ + + /* + * if connection drops request + * cant be completed + */ + if(!piiu->conn_up){ + return ECA_BADCHID; + } + + bytesAvailable = cacRingBufferWriteSize(&piiu->send, TRUE); } - pmsg = (struct extmsg *) (piiu->send->buf + piiu->send->stk); + pmsg = (struct extmsg *) &piiu->send.buf[piiu->send.wtix]; pmsg->m_postsize = extsize; + *ppMsg = pmsg; - return pmsg; + return ECA_NORMAL; } @@ -384,7 +533,18 @@ int ca_task_initialize() if(status != ECA_NORMAL){ return status; } -#endif +#endif /*vxWorks*/ + +#ifdef UNIX + /* + * dont allow disconnect to terminate process + * when running in UNIX enviroment + * + * allow error to be returned to sendto() + * instead of handling disconnect at interrupt + */ + signal(SIGPIPE,SIG_IGN); +#endif /*UNIX*/ if (repeater_installed()==FALSE) { spawn_repeater(); @@ -393,32 +553,62 @@ int ca_task_initialize() ca_temp = (struct ca_static *) calloc(1, sizeof(*ca_temp)); if (!ca_temp) - return ERROR; + return ECA_ALLOCMEM; #ifdef vxWorks if (ca_add_task_variable(ca_temp)<0){ free(ca_temp); return ECA_ALLOCMEM; } -#else +#else /* vxWorks */ ca_static = ca_temp; -#endif +#endif /* vxWorks */ ca_static->ca_exception_func = ca_default_exception_handler; ca_static->ca_exception_arg = NULL; + /* record a default user name */ + ca_static->ca_pUserName = localUserName(); + if(!ca_static->ca_pUserName){ + free(ca_static); + return ECA_ALLOCMEM; + } + + /* record a default user name */ + ca_static->ca_pLocationName = localLocationName(); + if(!ca_static->ca_pLocationName){ + free(ca_static->ca_pUserName); + free(ca_static); + return ECA_ALLOCMEM; + } + + /* init sync group facility */ + ca_sg_init(); + + ellInit(&ca_static->ca_iiuList); + ellInit(&ca_static->ca_ioeventlist); + ellInit(&ca_static->ca_free_event_list); + ellInit(&ca_static->ca_pend_read_list); + ellInit(&ca_static->ca_pend_write_list); +#ifdef vxWorks + ellInit(&ca_static->ca_local_chidlist); + ellInit(&ca_static->ca_dbfree_ev_list); + ellInit(&ca_static->ca_lcl_buff_list); + ellInit(&ca_static->ca_taskVarList); + ellInit(&ca_static->ca_putNotifyQue); +#endif /* vxWorks */ ca_static->ca_pBucket = bucketCreate(CLIENT_ID_WIDTH); if(!ca_static->ca_pBucket) abort(0); -#if defined(VMS) +#ifdef VMS { status = lib$get_ef(&io_done_flag); if (status != SS$_NORMAL) lib$signal(status); } -#else -# if defined(vxWorks) +#endif /*VMS*/ +#ifdef vxWorks { char name[15]; int status; @@ -427,17 +617,28 @@ int ca_task_initialize() ca_static->ca_local_ticks = LOCALTICKS; - FASTLOCKINIT(&client_lock); - FASTLOCKINIT(&event_lock); - io_done_sem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - if(!io_done_sem){ - abort(0); - } + ca_static->ca_client_lock = semMCreate(SEM_DELETE_SAFE); + assert(ca_static->ca_client_lock); + ca_static->ca_event_lock = semMCreate(SEM_DELETE_SAFE); + assert(ca_static->ca_event_lock); + ca_static->ca_putNotifyLock = semMCreate(SEM_DELETE_SAFE); + assert(ca_static->ca_putNotifyLock); + ca_static->ca_io_done_sem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); + assert(ca_static->ca_io_done_sem); + ca_static->ca_blockSem = + semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); + assert(ca_static->ca_blockSem); evuser = (void *) db_init_events(); if (!evuser) abort(0); + status = db_add_extra_labor_event( + evuser, + ca_extra_event_labor, + ca_static); + if(status) + abort(0); strcpy(name, "EV "); strncat( name, @@ -452,14 +653,7 @@ int ca_task_initialize() if (status != OK) abort(0); } -# else -# if defined(UNIX) -# else - @@@@ dont compile in this case @@@@ -# endif -# endif -#endif - +#endif /*vxWorks*/ } return ECA_NORMAL; } @@ -468,7 +662,7 @@ int ca_task_initialize() /* * create_udp_fd */ -void create_udp_fd() +LOCAL void create_udp_fd() { int pri; char name[64]; @@ -551,8 +745,10 @@ LOCAL void spawn_repeater() status = fork(); if (status < 0) SEVCHK(ECA_NOREPEATER, NULL); - if (status == 0) + if (status == 0){ ca_repeater_task(); + exit(0); + } } #endif #ifdef vxWorks @@ -680,13 +876,165 @@ int tid; ca_static = pcas; ptviu->tid = taskIdSelf(); + LOCK; ellAdd(&ca_static->ca_taskVarList, &ptviu->node); + UNLOCK; return ECA_NORMAL; } #endif + +/* + * CA_IMPORT_CANCEL() + */ +#ifdef vxWorks +int ca_import_cancel(tid) +int tid; +{ + int status; + TVIU *ptviu; + LOCK; + ptviu = (TVIU *) ca_static->ca_taskVarList.node.next; + while(ptviu){ + if(ptviu->tid == tid){ + break; + } + } + + if(!ptviu){ + return ECA_NOCACTX; + } + + ellDelete(&ca_static->ca_taskVarList, &ptviu->node); + UNLOCK; + + status = taskVarDelete(tid, (void *)&ca_static); + assert (status == OK); + + return ECA_NORMAL; +} +#endif + + +/* + * CA_MODIFY_CLIENT_LOCATION_NAME() + * + * Modify or override the default + * client location name. + */ +#ifdef __STDC__ +int ca_modify_client_location(char *pLocationName) +#else /*__STDC__*/ +int ca_modify_client_location(pLocationName) +char *pLocationName; +#endif /*__STDC__*/ +{ + char *pTmp; + unsigned size; + IIU *piiu; + + INITCHK; + + size = strlen(pLocationName)+1; + if (size > STRING_LIMIT){ + return ECA_STRTOBIG; + } + + pTmp = malloc(size); + if(!pTmp){ + return ECA_ALLOCMEM; + } + + if(ca_static->ca_pLocationName){ + free(ca_static->ca_pLocationName); + } + ca_static->ca_pLocationName = pTmp; + + /* + * force null termination + */ + strncpy( + ca_static->ca_pLocationName, + pLocationName, + size-1); + ca_static->ca_pLocationName[size-1]='\0'; + + /* + * update all servers we are currently + * attached to. + */ + LOCK; + piiu = (struct ioc_in_use *) ca_static->ca_iiuList.node.next; + while(piiu){ + issue_identify_client_location(piiu); + piiu = (struct ioc_in_use *) piiu->node.next; + } + UNLOCK; + + return ECA_NORMAL; +} + + + +/* + * CA_MODIFY_CLIENT_NAME() + * + * Modify or override the default + * client (user) name. + */ +#ifdef __STDC__ +int ca_modify_client_name(char *pClientName) +#else /*__STDC__*/ +int ca_modify_client_name(pClientName) +char *pClientName; +#endif /*__STDC__*/ +{ + char *pTmp; + unsigned size; + IIU *piiu; + + INITCHK; + + size = strlen(pClientName)+1; + if (size > STRING_LIMIT){ + return ECA_STRTOBIG; + } + + pTmp = malloc(size); + if(!pTmp){ + return ECA_ALLOCMEM; + } + + if(ca_static->ca_pUserName){ + free(ca_static->ca_pUserName); + } + ca_static->ca_pUserName = pTmp; + + /* + * force null termination + */ + strncpy( + ca_static->ca_pUserName, + pClientName, + size-1); + ca_static->ca_pUserName[size-1]='\0'; + + /* + * update all servers we are currently + * attached to. + */ + LOCK; + piiu = (struct ioc_in_use *) ca_static->ca_iiuList.node.next; + while(piiu){ + issue_identify_client(piiu); + piiu = (struct ioc_in_use *) piiu->node.next; + } + UNLOCK; + + return ECA_NORMAL; +} @@ -922,6 +1270,7 @@ LOCAL void ca_process_exit() /* * Cancel all local events + * (and put call backs) */ # ifdef vxWorks chix = (chid) & ca_temp->ca_local_chidlist.node; @@ -932,6 +1281,15 @@ LOCAL void ca_process_exit() abort(0); free(monix); } + if(chix->ppn){ + CACLIENTPUTNOTIFY *ppn; + + ppn = chix->ppn; + if(ppn->busy){ + dbNotifyCancel(&ppn->dbPutNotify); + } + free(ppn); + } } # endif @@ -963,8 +1321,10 @@ LOCAL void ca_process_exit() } free(ptviu); } - if(ca_temp->recv_tid != tid){ - taskDelete(ca_temp->recv_tid); + if(taskIdVerify(ca_temp->recv_tid)==OK){ + if(ca_temp->recv_tid != tid){ + taskDelete(ca_temp->recv_tid); + } } } # endif @@ -986,9 +1346,7 @@ LOCAL void ca_process_exit() # endif /* - * after activity eliminated: - */ - /* + * after activity eliminated * close all sockets before clearing chid blocks and remote * event blocks */ @@ -1006,8 +1364,6 @@ LOCAL void ca_process_exit() ECA_INTERNAL, "Corrupt iiu list- at close"); } - free((char *)piiu->send); - free((char *)piiu->recv); piiu = (struct ioc_in_use *) piiu->node.next; } @@ -1035,6 +1391,26 @@ LOCAL void ca_process_exit() } free((char *)chix); } + + /* + * free message body cache + */ + if(piiu->pCurData){ + free(piiu->pCurData); + piiu->pCurData = NULL; + piiu->curDataMax = 0; + } + +#ifdef VAX + /* + * free put convert cache + */ + if(piiu->pPutConvertBuf){ + free(piiu->pPutConvertBuf); + piiu->pPutConvertBuf = NULL; + piiu->putConvertBufSize = 0; + } +#endif piiu = (struct ioc_in_use *) piiu->node.next; } @@ -1042,8 +1418,7 @@ LOCAL void ca_process_exit() * remove local chid blocks, paddr blocks, waiting ev blocks */ # ifdef vxWorks - while (chix = (chid) ellGet(&ca_temp->ca_local_chidlist)) - free((char *)chix); + ellFree(&ca_temp->ca_local_chidlist); ellFree(&ca_temp->ca_dbfree_ev_list); # endif @@ -1051,6 +1426,13 @@ LOCAL void ca_process_exit() ellFree(&ca_temp->ca_free_event_list); /* remove any pending read blocks */ ellFree(&ca_temp->ca_pend_read_list); + /* remove any pending write blocks */ + ellFree(&ca_temp->ca_pend_write_list); + /* remove any pending io event blocks */ + ellFree(&ca_temp->ca_ioeventlist); + + /* reclaim sync group resources */ + ca_sg_shutdown(ca_temp); /* * force this macro to use ca_temp @@ -1060,16 +1442,16 @@ LOCAL void ca_process_exit() # undef ca_static # if defined(vxWorks) - if(FASTLOCKFREE(&ca_temp->ca_client_lock) < 0) - ca_signal(ECA_INTERNAL, "couldnt free memory"); - if(FASTLOCKFREE(&ca_temp->ca_event_lock) < 0) - ca_signal(ECA_INTERNAL, "couldnt free memory"); - status = semDelete(ca_temp->ca_io_done_sem); - if(status < 0){ - ca_signal( - ECA_INTERNAL, - "couldnt free sem"); - } + assert(semDelete(ca_temp->ca_client_lock)==OK); + assert(semDelete(ca_temp->ca_event_lock)==OK); + assert(semDelete(ca_temp->ca_putNotifyLock)==OK); + assert(semDelete(ca_temp->ca_io_done_sem)==OK); + assert(semDelete(ca_temp->ca_blockSem)==OK); +# endif + +# if defined(VMS) + status = lib$free_ef(&ca_temp->ca_io_done_flag); + assert(status == SS$_NORMAL) # endif /* @@ -1077,6 +1459,20 @@ LOCAL void ca_process_exit() */ ellFree(&ca_temp->ca_iiuList); + /* + * free user name string + */ + if(ca_temp->ca_pUserName){ + free(ca_temp->ca_pUserName); + } + + /* + * free location name string + */ + if(ca_temp->ca_pLocationName){ + free(ca_temp->ca_pLocationName); + } + /* * free top level bucket */ @@ -1182,6 +1578,7 @@ int ca_build_and_connect /* Find out quickly if channel is on this node */ status = db_name_to_addr(name_str, &tmp_paddr); if (status == OK) { + int size; /* * allocate CHIU (channel in use) block @@ -1189,11 +1586,11 @@ int ca_build_and_connect * also allocate enough for the channel name & paddr * block */ - *chixptr = chix = (chid) malloc(sizeof(*chix) - + strcnt + sizeof(struct db_addr)); - if (!chix) - abort(0); - + size = sizeof(*chix) + strcnt + sizeof(struct db_addr); + *chixptr = chix = (chid) calloc(1,size); + if (!chix){ + return ECA_ALLOCMEM; + } chix->id.paddr = (struct db_addr *) (strcnt + (char *) (chix + 1)); *chix->id.paddr = tmp_paddr; @@ -1246,7 +1643,7 @@ int ca_build_and_connect /* allocate CHIU (channel in use) block */ /* also allocate enough for the channel name */ - *chixptr = chix = (chid) malloc(sizeof(*chix) + strcnt); + *chixptr = chix = (chid) calloc(1, sizeof(*chix) + strcnt); if (!chix){ return ECA_ALLOCMEM; } @@ -1257,8 +1654,8 @@ int ca_build_and_connect if(status != BUCKET_SUCCESS){ *chixptr = (chid) NULL; free((char *) chix); - status = ECA_ALLOCMEM; - goto exit; + UNLOCK; + return ECA_ALLOCMEM; } chix->puser = puser; @@ -1289,6 +1686,8 @@ int ca_build_and_connect piiuCast->next_retry = CA_CURRENT_TIME; piiuCast->retry_delay = CA_RECAST_DELAY; + UNLOCK; + build_msg(chix, DONTREPLY); if (!chix->connection_func) { SETPENDRECV; @@ -1296,12 +1695,7 @@ int ca_build_and_connect SETPENDRECV; } - status = ECA_NORMAL; - -exit: - UNLOCK; - - return status; + return ECA_NORMAL; } @@ -1324,6 +1718,7 @@ chid chix; int reply_type; #endif { + int status; int size; int cmd; struct extmsg *mptr; @@ -1339,9 +1734,10 @@ int reply_type; cmd = IOC_SEARCH; } - mptr = CAC_ALLOC_MSG(piiu, size); - if(!mptr){ - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); + LOCK; + status = CAC_ALLOC_MSG(piiu, size, &mptr); + if(status != ECA_NORMAL){ + ca_printf("%s: %s\n",__FILE__,ca_message(status)); return; } @@ -1370,6 +1766,8 @@ int reply_type; CAC_ADD_MSG(piiu); + UNLOCK; + piiu->send_needed = TRUE; } @@ -1396,9 +1794,8 @@ void *pvalue void *pvalue; #endif { - register struct extmsg *mptr; - unsigned size=0; - struct ioc_in_use *piiu; + struct extmsg hdr; + int status; CHIXCHK(chix); @@ -1427,32 +1824,20 @@ void *pvalue } #endif - LOCK; - piiu = chix->piiu; - mptr = CAC_ALLOC_MSG(piiu, size); - if(!mptr){ - UNLOCK; - return ECA_TOLARGE; - } - /* * msg header only on db read req */ - mptr->m_cmmd = htons(IOC_READ); - mptr->m_type = htons(type); - mptr->m_available = (long) pvalue; - mptr->m_count = htons(count); - mptr->m_cid = chix->id.sid; + hdr.m_cmmd = htons(IOC_READ); + hdr.m_type = htons(type); + hdr.m_available = (long) pvalue; + hdr.m_count = htons(count); + hdr.m_cid = chix->id.sid; + hdr.m_postsize = 0; - CAC_ADD_MSG(piiu); - - /* - * keep track of the number of messages - * outstanding on this connection that - * require a response - */ - piiu->outstanding_ack_count++; - UNLOCK; + status = cac_push_msg(chix->piiu, &hdr, 0); + if(status != ECA_NORMAL){ + return status; + } SETPENDRECV; @@ -1513,25 +1898,26 @@ int ca_array_get_callback LOCK; if (!(monix = (evid) ellGet(&free_event_list))) - monix = (evid) malloc(sizeof *monix); + monix = (evid) malloc(sizeof(*monix)); + UNLOCK; if (monix) { + memset(monix, 0, sizeof(*monix)); monix->chan = chix; monix->usr_func = pfunc; monix->usr_arg = arg; monix->type = type; monix->count = count; + LOCK; ellAdd(&pend_read_list, &monix->node); + UNLOCK; - issue_get_callback(monix); - - status = ECA_NORMAL; + status = issue_get_callback(monix); } else status = ECA_ALLOCMEM; - UNLOCK; return status; } @@ -1543,16 +1929,16 @@ int ca_array_get_callback * (lock must be on) */ #ifdef __STDC__ -LOCAL void issue_get_callback(evid monix) +LOCAL int issue_get_callback(evid monix) #else -LOCAL void issue_get_callback(monix) +LOCAL int issue_get_callback(monix) evid monix; #endif { - register chid chix = monix->chan; - unsigned size = 0; + int status; + chid chix = monix->chan; unsigned count; - register struct extmsg *mptr; + struct extmsg hdr; struct ioc_in_use *piiu; piiu = chix->piiu; @@ -1562,7 +1948,7 @@ evid monix; * (it will be sent once connected) */ if(chix->state != cs_conn){ - return; + return ECA_BADCHID; } /* @@ -1575,58 +1961,49 @@ evid monix; count = monix->count; } - mptr = CAC_ALLOC_MSG(piiu, size); - if(!mptr){ - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); - return; - } - /* msg header only on db read notify req */ - mptr->m_cmmd = htons(IOC_READ_NOTIFY); - mptr->m_type = htons(monix->type); - mptr->m_available = (long) monix; - mptr->m_count = htons(count); - mptr->m_cid = chix->id.sid; + hdr.m_cmmd = htons(IOC_READ_NOTIFY); + hdr.m_type = htons(monix->type); + hdr.m_available = (long) monix; + hdr.m_count = htons(count); + hdr.m_postsize = 0; + hdr.m_cid = chix->id.sid; - CAC_ADD_MSG(piiu); - - /* - * keep track of the number of messages - * outstanding on this connection that - * require a response - */ - piiu->outstanding_ack_count++; + status = cac_push_msg(piiu, &hdr, 0); piiu->send_needed = TRUE; + + return status; } /* - * CA_ARRAY_PUT() - * + * CA_ARRAY_PUT_CALLBACK() * */ -int ca_array_put #ifdef __STDC__ +int ca_array_put_callback ( chtype type, unsigned long count, chid chix, -void *pvalue +void *pvalue, +void (*pfunc)(struct event_handler_args), +void *usrarg ) -#else -(type,count,chix,pvalue) +#else /*__STDC__*/ +int ca_array_put_callback(type,count,chix,pvalue,pfunc,usrarg) chtype type; unsigned long count; chid chix; void *pvalue; -#endif +void (*pfunc)(); +void *usrarg; +#endif /*__STDC__*/ { - struct extmsg *mptr; - int postcnt; - void *pdest; - unsigned size_of_one; - int i; + IIU *piiu; + int status; + evid monix; /* * valid channel id test @@ -1645,25 +2022,352 @@ void *pvalue; if(count > chix->count || count == 0) return ECA_BADCOUNT; + piiu = chix->piiu; + + if(!CA_V41(CA_PROTOCOL_VERSION, piiu->minor_version_number)){ + return ECA_NOSUPPORT; + } + + if(piiu){ + LOCK; + monix = (evid) ellGet(&free_event_list); + UNLOCK; + if (!monix){ + monix = (evid) malloc(sizeof(*monix)); + } + if (!monix){ + return ECA_ALLOCMEM; + } + + memset(monix,0,sizeof(*monix)); + monix->chan = chix; + monix->usr_func = pfunc; + monix->usr_arg = usrarg; + monix->type = type; + monix->count = count; + } #ifdef vxWorks - { + else{ + CACLIENTPUTNOTIFY *ppn; + int size; + + size = dbr_size_n(type,count); + LOCK; + + ppn = chix->ppn; + if(ppn){ + /* + * wait while it is busy + */ + if(ppn->busy){ + UNLOCK; + status = semTake( + ca_static->ca_blockSem, + sysClkRateGet()*60); + if(status != OK){ + return ECA_PUTCBINPROG; + } + LOCK; + } + + /* + * if not busy then free the current + * block if it is to small + */ + if(ppn->valueSizeppn = NULL; + } + } + + if(!ppn){ + ppn = (CACLIENTPUTNOTIFY *) + calloc(1, sizeof(*ppn)+size); + if(!ppn){ + UNLOCK; + return ECA_ALLOCMEM; + } + chix->ppn = ppn; + ppn->pcas = ca_static; + ppn->dbPutNotify.userCallback = + ca_put_notify_action; + ppn->dbPutNotify.usrPvt = chix; + ppn->dbPutNotify.paddr = chix->id.paddr; + ppn->dbPutNotify.pbuffer = (ppn+1); + } + ppn->busy = TRUE; + ppn->caUserCallback = pfunc; + ppn->caUserArg = usrarg; + ppn->dbPutNotify.nRequest = count; + memcpy(ppn->dbPutNotify.pbuffer, (char *)pvalue, size); + status = dbPutNotifyMapType(&ppn->dbPutNotify, type); + if(status){ + UNLOCK; + ppn->busy = FALSE; + return ECA_PUTFAIL; + } + status = dbPutNotify(&ppn->dbPutNotify); + UNLOCK; + if(status){ + if(status==S_db_Blocked){ + return ECA_PUTCBINPROG; + } + ppn->busy = FALSE; + return ECA_PUTFAIL; + } + return ECA_NORMAL; + } +#endif /*vxWorks*/ + + status = issue_ca_array_put( + IOC_WRITE_NOTIFY, + (unsigned long)monix, + type, + count, + chix, + pvalue); + if(status != ECA_NORMAL){ + if(chix->piiu){ + LOCK; + ellAdd(&free_event_list, &monix->node); + UNLOCK; + } + return status; + } + + + if(piiu){ + LOCK; + ellAdd(&pend_write_list, &monix->node); + UNLOCK; + } + + return status; +} + + +/* + * CA_PUT_NOTIFY_ACTION + */ +#ifdef vxWorks +LOCAL void ca_put_notify_action(PUTNOTIFY *ppn) +{ + CACLIENTPUTNOTIFY *pcapn; + struct ioc_in_use *piiu; + struct ca_static *pcas; + chid chix; + + /* + * we choose to suspend the task if there + * is an internal failure + */ + chix = (chid) ppn->usrPvt; + if(!chix){ + taskSuspend(0); + } + if(!chix->ppn){ + taskSuspend(0); + } + + piiu = chix->piiu; + pcapn = chix->ppn; + pcas = pcapn->pcas; + + /* + * independent lock used here in order to + * avoid any possibility of blocking + * the database (or indirectly blocking + * one client on another client). + */ + semTake(pcas->ca_putNotifyLock, WAIT_FOREVER); + ellAdd(&pcas->ca_putNotifyQue, &pcapn->node); + semGive(pcas->ca_putNotifyLock); + + /* + * offload the labor for this to the + * event task so that we never block + * the db or another client. + */ + db_post_extra_labor(pcas->ca_evuser); + +} +#endif /*vxWorks*/ + + +/* + * CA_EXTRA_EVENT_LABOR + */ +#ifdef vxWorks +LOCAL void ca_extra_event_labor(void *pArg) +{ + int status; + CACLIENTPUTNOTIFY *ppnb; + struct ca_static *pcas; + struct event_handler_args args; + + pcas = pArg; + + while(TRUE){ + /* + * independent lock used here in order to + * avoid any possibility of blocking + * the database (or indirectly blocking + * one client on another client). + */ + semTake(pcas->ca_putNotifyLock, WAIT_FOREVER); + ppnb = (CACLIENTPUTNOTIFY *)ellGet(&pcas->ca_putNotifyQue); + semGive(pcas->ca_putNotifyLock); + + /* + * break to loop exit + */ + if(!ppnb){ + break; + } + + /* + * setup arguments and call user's function + */ + args.usr = ppnb->caUserArg; + args.chid = ppnb->dbPutNotify.usrPvt; + args.type = ppnb->dbPutNotify.dbrType; + args.count = ppnb->dbPutNotify.nRequest; + args.dbr = NULL; + if(ppnb->dbPutNotify.status){ + if(ppnb->dbPutNotify.status == S_db_Blocked){ + args.status = ECA_PUTCBINPROG; + } + else{ + args.status = ECA_PUTFAIL; + } + } + else{ + args.status = ECA_NORMAL; + } + + LOCKEVENTS; + (*ppnb->caUserCallback) (args); + UNLOCKEVENTS; + + ppnb->busy = FALSE; + } + + /* + * wakeup the TCP thread if it is waiting for a cb to complete + */ + status = semGive(pcas->ca_blockSem); + if(status != OK){ + logMsg("CA block sem corrupted\n", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + } + +} +#endif /*vxWorks*/ + + +/* + * CA_ARRAY_PUT() + * + * + */ +int ca_array_put +#ifdef __STDC__ +( +chtype type, +unsigned long count, +chid chix, +void *pvalue +) +#else /*__STDC__*/ +(type,count,chix,pvalue) +chtype type; +unsigned long count; +chid chix; +void *pvalue; +#endif /*__STDC__*/ +{ + /* + * valid channel id test + */ + CHIXCHK(chix); + + /* + * compound types not allowed + */ + if(INVALID_DB_FIELD(type)) + return ECA_BADTYPE; + + /* + * check for valid count + */ + if(count > chix->count || count == 0) + return ECA_BADCOUNT; + +#ifdef vxWorks + /* + * If channel is on this client's host then + * call the database directly + */ + if(!chix->piiu){ int status; - if(!chix->piiu){ - status = db_put_field( chix->id.paddr, - type, - pvalue, - count); - if(status==OK) - return ECA_NORMAL; - else - return ECA_PUTFAIL; - } + status = db_put_field( chix->id.paddr, + type, + pvalue, + count); + if(status==OK) + return ECA_NORMAL; + else + return ECA_PUTFAIL; } -#endif +#endif /*vxWorks*/ - size_of_one = dbr_size[type]; - postcnt = size_of_one*count; + return issue_ca_array_put(IOC_WRITE, ~0L, type, count, chix, pvalue); +} + + +/* + * issue_ca_array_put() + */ +#ifdef __STDC__ +static int issue_ca_array_put +( +unsigned cmd, +unsigned long avail, +chtype type, +unsigned long count, +chid chix, +void *pvalue +) +#else /*__STDC__*/ +static int issue_ca_array_put(cmd, avail, type, count, chix, pvalue) +unsigned cmd; +unsigned long avail; +chtype type; +unsigned long count; +chid chix; +void *pvalue; +#endif /*__STDC__*/ +{ + int status; + struct ioc_in_use *piiu; + struct extmsg hdr; + int postcnt; +#ifdef VAX + void *pdest; +#endif + unsigned size_of_one; + int i; + + + piiu = chix->piiu; + size_of_one = dbr_size[type]; + postcnt = dbr_size_n(type,count); /* * @@ -1691,16 +2395,21 @@ void *pvalue; LOCK; - mptr = CAC_ALLOC_MSG(chix->piiu, postcnt); - if(!mptr){ - UNLOCK; - return ECA_TOLARGE; - } - - pdest = (void *)(mptr+1); - - #ifdef VAX + if(piiu->putConvertBufSizepPutConvertBuf){ + free(piiu->pPutConvertBuf); + } + piiu->putConvertBufSize = 0; + piiu->pPutConvertBuf = malloc(postcnt); + if(!piiu->pPutConvertBuf){ + UNLOCK; + return ECA_ALLOCMEM; + } + piiu->putConvertBufSize = postcnt; + } + pdest = piiu->pPutConvertBuf; + /* * No compound types here because these types are read only * and therefore only appropriate for gets or monitors @@ -1719,7 +2428,7 @@ void *pvalue; case DBR_SHORT: #if DBR_INT != DBR_SHORT case DBR_INT: -#endif +#endif /*DBR_INT != DBR_SHORT*/ *(short *)pdest = htons(*(short *)pvalue); break; @@ -1737,25 +2446,29 @@ void *pvalue; case DBR_DOUBLE: /* no cvrs for double yet */ default: + UNLOCK; return ECA_BADTYPE; } (char *) pdest += size_of_one; (char *) pvalue += size_of_one; } -#else - memcpy(pdest,pvalue,postcnt); -#endif + + pvalue = pdest; +#endif /*VAX*/ - mptr->m_cmmd = htons(IOC_WRITE); - mptr->m_type = htons(type); - mptr->m_count = htons(count); - mptr->m_cid = chix->id.sid; - mptr->m_available = ~0L; + hdr.m_cmmd = htons(cmd); + hdr.m_type = htons(type); + hdr.m_count = htons(count); + hdr.m_cid = chix->id.sid; + hdr.m_available = avail; + hdr.m_postsize = postcnt; + + status = cac_push_msg(piiu, &hdr, pvalue); - CAC_ADD_MSG(((IIU *)chix->piiu)); UNLOCK; + piiu->send_needed = TRUE; - return ECA_NORMAL; + return status; } @@ -1863,12 +2576,13 @@ void *astarg; if(pndrecvcnt<1) (*ast)(astarg); else{ - LOCK; pioe = (struct pending_io_event *) malloc(sizeof(*pioe)); if(!pioe) return ECA_ALLOCMEM; + memset(pioe,0,sizeof(*pioe)); pioe->io_done_arg = astarg; pioe->io_done_sub = ast; + LOCK; ellAdd(&ioeventlist, &pioe->node); UNLOCK; } @@ -1912,9 +2626,11 @@ evid *monixptr; long mask; #endif { - register evid monix; - register int status; + evid monix; + int status; + int size; + INITCHK; LOOSECHIXCHK(chix); if(INVALID_DB_REQ(type)) @@ -1938,24 +2654,31 @@ long mask; if(!dbevsize) dbevsize = db_sizeof_event_block(); - - if(!(monix = (evid)ellGet(&dbfree_ev_list))) - monix = (evid)malloc(sizeof(*monix)+dbevsize); + size = sizeof(*monix)+dbevsize; + if(!(monix = (evid)ellGet(&dbfree_ev_list))){ + monix = (evid)malloc(size); + } + } + else{ + size = sizeof(*monix); + if(!(monix = (evid)ellGet(&free_event_list))){ + monix = (evid)malloc(size); + } } - else - if(!(monix = (evid)ellGet(&free_event_list))) - monix = (evid)malloc(sizeof *monix); } # else + size = sizeof(*monix); if(!(monix = (evid)ellGet(&free_event_list))) - monix = (evid) malloc(sizeof *monix); + monix = (evid) malloc(size); # endif if(!monix){ - status = ECA_ALLOCMEM; - goto unlock_rtn; + UNLOCK; + return ECA_ALLOCMEM; } + memset(monix,0,size); + /* they dont have to supply one if they dont want to */ if(monixptr) *monixptr = monix; @@ -1981,8 +2704,8 @@ long mask; mask, monix+1); if(status == ERROR){ - status = ECA_DBLCLFAIL; - goto unlock_rtn; + UNLOCK; + return ECA_DBLCLFAIL; } /* @@ -1999,13 +2722,12 @@ long mask; to force the first (untriggered) event. */ if(db_post_single_event(monix+1)==ERROR){ - status = ECA_OVEVFAIL; - goto unlock_rtn; + UNLOCK; + return ECA_OVEVFAIL; } - status = ECA_NORMAL; - goto unlock_rtn; - + UNLOCK; + return ECA_NORMAL; } } # endif @@ -2014,35 +2736,28 @@ long mask; /* Place in the channel list */ ellAdd(&chix->eventq, &monix->node); - ca_request_event(monix); - - status = ECA_NORMAL; - -unlock_rtn: - UNLOCK; - return status; + return ca_request_event(monix); } /* * CA_REQUEST_EVENT() - * - * LOCK must be applied while in this routine */ #ifdef __STDC__ -void ca_request_event(evid monix) +int ca_request_event(evid monix) #else -void ca_request_event(monix) +int ca_request_event(monix) evid monix; #endif { - register chid chix = monix->chan; - unsigned size = sizeof(struct mon_info); + int status; + chid chix = monix->chan; unsigned count; - register struct monops *mptr; + struct monops msg; struct ioc_in_use *piiu; + piiu = chix->piiu; @@ -2051,7 +2766,7 @@ evid monix; * (it will be sent once connected) */ if(chix->state != cs_conn){ - return; + return ECA_BADCHID; } /* @@ -2065,28 +2780,25 @@ evid monix; count = monix->count; } - mptr = (struct monops *) CAC_ALLOC_MSG(piiu, size); - if(!mptr){ - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); - return; - } - /* msg header */ - mptr->m_header.m_cmmd = htons(IOC_EVENT_ADD); - mptr->m_header.m_available = (long) monix; - mptr->m_header.m_type = htons(monix->type); - mptr->m_header.m_count = htons(count); - mptr->m_header.m_cid = chix->id.sid; + msg.m_header.m_cmmd = htons(IOC_EVENT_ADD); + msg.m_header.m_available = (long) monix; + msg.m_header.m_type = htons(monix->type); + msg.m_header.m_count = htons(count); + msg.m_header.m_cid = chix->id.sid; + msg.m_header.m_postsize = sizeof(msg.m_info); /* msg body */ - htonf(&monix->p_delta, &mptr->m_info.m_hval); - htonf(&monix->n_delta, &mptr->m_info.m_lval); - htonf(&monix->timeout, &mptr->m_info.m_toval); - mptr->m_info.m_mask = htons(monix->mask); + htonf(&monix->p_delta, &msg.m_info.m_hval); + htonf(&monix->n_delta, &msg.m_info.m_lval); + htonf(&monix->timeout, &msg.m_info.m_toval); + msg.m_info.m_mask = htons(monix->mask); - CAC_ADD_MSG(piiu); + status = cac_push_msg(piiu, &msg.m_header, &msg.m_info); piiu->send_needed = TRUE; + + return status; } @@ -2140,10 +2852,7 @@ void *pfl; status = OK; } else{ - if(count == 1) - size = dbr_size[type]; - else - size = (count-1)*dbr_value_size[type]+dbr_size[type]; + size = dbr_size_n(type,count); if( size <= sizeof(valbuf) ){ pval = (void *) &valbuf; @@ -2172,11 +2881,13 @@ void *pfl; if(!pbuf){ pbuf = (struct tmp_buff *) malloc(sizeof(*pbuf)+size); - if(!pbuf) - abort(0); + if(!pbuf){ + ca_printf("%s: No Mem, Event Discarded\n", + __FILE__); + return; + } pbuf->size = size; } - pval = (void *) (pbuf+1); } } @@ -2189,33 +2900,26 @@ void *pfl; pfl); /* - * I would like to tell um with the event handler but this would - * not be upward compatible. so I run the exception handler. + * Call user's callback */ LOCKEVENTS; - if(status == ERROR){ - if(ca_static->ca_exception_func){ - struct exception_handler_args args; + { + struct event_handler_args args; + + args.usr = monix->usr_arg; + args.chid = monix->chan; + args.type = type; + args.count = count; + args.dbr = pval; - args.usr = ca_static->ca_exception_arg; - args.chid = monix->chan; - args.type = type; - args.count = count; - args.addr = NULL; - args.stat = ECA_GETFAIL; - args.op = CA_OP_GET; - args.ctx = "Event lost due to local get fail\n"; + if(status == OK){ + args.status = ECA_NORMAL; + } + else{ + args.status = ECA_GETFAIL; + } - (*ca_static->ca_exception_func)(args); - } - } - else{ - (*monix->usr_func)( - monix->usr_arg, - monix->chan, - type, - count, - pval); + (*monix->usr_func)(args); } UNLOCKEVENTS; @@ -2274,11 +2978,23 @@ int ca_clear_event evid monix; #endif { - register chid chix = monix->chan; - register struct extmsg *mptr; + int status; + chid chix = monix->chan; + struct extmsg hdr; + /* + * is it a valid channel ? + */ LOOSECHIXCHK(chix); + /* + * is it a valid monitor id + */ + status = ellFind(&chix->eventq, &monix->node); + if(status==ERROR){ + return ECA_BADMONID; + } + /* disable any further events from this event block */ monix->usr_func = NULL; @@ -2290,20 +3006,14 @@ evid monix; * dont allow two threads to delete the same moniitor at once */ LOCK; - status = ellFind(&chix->eventq, &monix->node); - if (status != ERROR) { - ellDelete(&chix->eventq, &monix->node); - status = db_cancel_event(monix + 1); - } - UNLOCK; - if (status == ERROR) - return ECA_BADMONID; - + ellDelete(&chix->eventq, &monix->node); + status = db_cancel_event(monix + 1); ellAdd(&dbfree_ev_list, &monix->node); + UNLOCK; return ECA_NORMAL; } -#endif +#endif /*vxWorks*/ /* * dont send the message if the conn is down (just delete from the @@ -2311,44 +3021,36 @@ evid monix; * * check for conn down while locked to avoid a race */ - LOCK; if(chix->state == cs_conn){ struct ioc_in_use *piiu; piiu = chix->piiu; - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - UNLOCK; - return ECA_TOLARGE; - } - /* msg header */ - mptr->m_cmmd = htons(IOC_EVENT_CANCEL); - mptr->m_available = (long) monix; - mptr->m_type = chix->type; - mptr->m_count = chix->count; - mptr->m_cid = chix->id.sid; + hdr.m_cmmd = htons(IOC_EVENT_CANCEL); + hdr.m_available = (long) monix; + hdr.m_type = htons(chix->type); + hdr.m_count = htons(chix->count); + hdr.m_cid = chix->id.sid; + hdr.m_postsize = 0; + status = cac_push_msg(piiu, &hdr, NULL); + /* * NOTE: I free the monitor block only * after confirmation from IOC */ - CAC_ADD_MSG(piiu); - - /* - * keep track of the number of messages outstanding on this - * connection that require a response - */ - piiu->outstanding_ack_count++; } else{ + LOCK; ellDelete(&monix->chan->eventq, &monix->node); + UNLOCK; + status = ECA_NORMAL; } - UNLOCK; - return ECA_NORMAL; + return status; } + /* * @@ -2374,9 +3076,9 @@ chid chix; #endif { int status; - register evid monix; + evid monix; struct ioc_in_use *piiu = chix->piiu; - register struct extmsg *mptr; + struct extmsg hdr; enum channel_state old_chan_state; LOOSECHIXCHK(chix); @@ -2388,102 +3090,103 @@ chid chix; /* the while is only so I can break to the lock exit */ LOCK; - while (TRUE) { - /* disable any further events from this channel */ - for (monix = (evid) chix->eventq.node.next; - monix; - monix = (evid) monix->node.next) + /* disable any further events from this channel */ + for (monix = (evid) chix->eventq.node.next; + monix; + monix = (evid) monix->node.next) + monix->usr_func = NULL; + /* disable any further get callbacks from this channel */ + for (monix = (evid) pend_read_list.node.next; + monix; + monix = (evid) monix->node.next) + if (monix->chan == chix) + monix->usr_func = NULL; + /* disable any further put callbacks from this channel */ + for (monix = (evid) pend_write_list.node.next; + monix; + monix = (evid) monix->node.next) + if (monix->chan == chix) monix->usr_func = NULL; - /* disable any further get callbacks from this channel */ - for (monix = (evid) pend_read_list.node.next; - monix; - monix = (evid) monix->node.next) - if (monix->chan == chix) - monix->usr_func = NULL; #ifdef vxWorks - if (!chix->piiu) { - int status; + if (!chix->piiu) { + CACLIENTPUTNOTIFY *ppn; + int status; - /* - * clear out the events for this channel - */ - while (monix = (evid) ellGet(&chix->eventq)) { - status = db_cancel_event(monix + 1); - if (status == ERROR) - abort(0); - ellAdd(&dbfree_ev_list, &monix->node); - } - - /* - * clear out this channel - */ - ellDelete(&local_chidlist, &chix->node); - free((char *) chix); - - break; /* to unlock exit */ + /* + * clear out the events for this channel + */ + while (monix = (evid) ellGet(&chix->eventq)) { + status = db_cancel_event(monix + 1); + assert (status == OK); + ellAdd(&dbfree_ev_list, &monix->node); } + + /* + * cancel any outstanding put notifies + */ + if(chix->ppn){ + ppn = chix->ppn; + if(ppn->busy){ + dbNotifyCancel(&ppn->dbPutNotify); + } + free(ppn); + } + + /* + * clear out this channel + */ + ellDelete(&local_chidlist, &chix->node); + free((char *) chix); + + UNLOCK; + return ECA_NORMAL; + } #endif - /* - * dont send the message if not conn - * (just delete from the queue and return) - * - * check for conn state while locked to avoid a race - */ - if(old_chan_state != cs_conn){ - ellConcat(&free_event_list, &chix->eventq); - ellDelete(&piiu->chidlist, &chix->node); - status = bucketRemoveItem(pBucket, chix->cid, chix); - if(status != BUCKET_SUCCESS){ - ca_signal( - ECA_INTERNAL, - "bad id at channel delete"); - } - free((char *) chix); - break; /* to unlock exit */ - } - - /* - * clear events and all other resources for this chid on the - * IOC - */ - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - UNLOCK; - return ECA_TOLARGE; - } - - /* msg header */ - mptr->m_cmmd = htons(IOC_CLEAR_CHANNEL); - mptr->m_available = (int) chix; - mptr->m_type = 0; - mptr->m_count = 0; - mptr->m_cid = chix->id.sid; - - /* - * NOTE: I free the chid and monitor blocks only after - * confirmation from IOC - */ - - CAC_ADD_MSG(piiu); - - /* - * keep track of the number of messages - * outstanding on this connection that - * require a response - */ - piiu->outstanding_ack_count++; - - break; /* to unlock exit */ - } /* - * message about unexecuted code from SUN's cheaper cc is a compiler - * bug + * dont send the message if not conn + * (just delete from the queue and return) + * + * check for conn state while locked to avoid a race */ + if(old_chan_state != cs_conn){ + ellConcat(&free_event_list, &chix->eventq); + ellDelete(&piiu->chidlist, &chix->node); + status = bucketRemoveItem(pBucket, chix->cid, chix); + if(status != BUCKET_SUCCESS){ + ca_signal( + ECA_INTERNAL, + "bad id at channel delete"); + } + free((char *) chix); + UNLOCK; + return ECA_NORMAL; + } + + /* + * clear events and all other resources for this chid on the + * IOC + */ + + /* msg header */ + hdr.m_cmmd = htons(IOC_CLEAR_CHANNEL); + hdr.m_available = (int) chix; + hdr.m_type = htons(0); + hdr.m_count = htons(0); + hdr.m_cid = chix->id.sid; + hdr.m_postsize = 0; + + status = cac_push_msg(piiu, &hdr, NULL); + + /* + * NOTE: I free the chid and monitor blocks only after + * confirmation from IOC + */ + UNLOCK; - return ECA_NORMAL; + return status; } @@ -2502,7 +3205,6 @@ chid chix; */ /************************************************************************/ /* This routine pends waiting for channel events and calls the */ -/* function specified with add_event when one occurs. If the */ /* timeout is specified as 0 infinite timeout is assumed. */ /* if the argument early is specified TRUE then CA_NORMAL is */ /* returned early (prior to timeout experation) when outstanding */ @@ -2525,14 +3227,13 @@ int early; return ECA_EVDISALLOW; } + manage_conn(TRUE); + /* * Flush the send buffers */ if(pndrecvcnt<1 && early){ - LOCK; - manage_conn(TRUE); - cac_send_msg(); - UNLOCK; + ca_flush_io(); return ECA_NORMAL; } @@ -2541,8 +3242,6 @@ int early; */ if((timeout*SYSFREQ)0 && early){ ca_pend_io_cleanup(); } @@ -2551,8 +3250,7 @@ int early; * also takes care of outstanding recvs * under UNIX */ - cac_send_msg(); - UNLOCK; + ca_flush_io(); if(pndrecvcnt<1 && early){ return ECA_NORMAL; @@ -2565,30 +3263,23 @@ int early; beg_time = time(NULL); while(TRUE){ - /* - * also takes care of outstanding recvs - * under UNIX - */ - LOCK; - manage_conn(TRUE); - cac_send_msg(); - UNLOCK; - -#if defined(UNIX) +# ifdef UNIX { struct timeval itimeout; itimeout.tv_usec = LOCALTICKS; itimeout.tv_sec = 0; - LOCK; - recv_msg_select(&itimeout); - UNLOCK; + ca_mux_io(&itimeout, CA_DO_RECVS | CA_DO_SENDS); } -# else -# if defined(vxWorks) +# else /*UNIX*/ + ca_flush_io(); +# endif /*UNIX*/ + +# ifdef vxWorks semTake(io_done_sem, LOCALTICKS); -# else -# if defined(VMS) +# endif /*vxWorks*/ + +# ifdef VMS { int status; unsigned int systim[2]={-LOCALTICKS,~0}; @@ -2605,11 +3296,7 @@ int early; if(status != SS$_NORMAL) lib$signal(status); } -# else - @@@@ dont compile in this case @@@@ -# endif -# endif -# endif +# endif /*VMS*/ if(pndrecvcnt<1 && early) @@ -2617,16 +3304,15 @@ int early; if(timeout != 0.0){ if(timeout < time(NULL)-beg_time){ - LOCK; - manage_conn(!early); if(early){ ca_pend_io_cleanup(); } - cac_send_msg(); - UNLOCK; + ca_flush_io(); return ECA_TIMEOUT; } } + + manage_conn(TRUE); } } @@ -2637,39 +3323,29 @@ int early; * send a sync to each IOC and back. dont * count reads until we recv the sync * - * LOCK must be on */ LOCAL void ca_pend_io_cleanup() { struct ioc_in_use *piiu; + LOCK; for( piiu = (IIU *) iiuList.node.next; piiu; piiu = (IIU *) piiu->node.next){ - struct extmsg *mptr; + struct extmsg hdr; if(piiu == piiuCast || !piiu->conn_up){ continue; } piiu->cur_read_seq++; - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); - return; - } - *mptr = nullmsg; - mptr->m_cmmd = htons(IOC_READ_SYNC); - CAC_ADD_MSG(piiu); - /* - * keep track of the number of messages - * outstanding on this connection that - * require a response - */ - piiu->outstanding_ack_count++; + hdr = nullmsg; + hdr.m_cmmd = htons(IOC_READ_SYNC); + cac_push_msg(piiu, &hdr, NULL); } + UNLOCK; pndrecvcnt = 0; } @@ -2679,6 +3355,7 @@ LOCAL void ca_pend_io_cleanup() /* * CA_FLUSH_IO() * + * Flush the send buffer * */ int ca_flush_io @@ -2688,22 +3365,56 @@ int ca_flush_io () #endif { + struct ioc_in_use *piiu; + struct timeval timeout; + int pending; + unsigned long bytesPending; - INITCHK; + INITCHK; - /* Flush the send buffers */ - LOCK; - cac_send_msg(); - UNLOCK; + pending = TRUE; + timeout.tv_usec = 0; + timeout.tv_sec = 0; + while(pending){ - return ECA_NORMAL; + /* + * perform socket io + * and process recv backlog + */ +# ifdef UNIX + ca_mux_io(&timeout, CA_DO_RECVS | CA_DO_SENDS); +# endif /*UNIX*/ + + /* + * wait for all buffers to flush + */ + pending = FALSE; + LOCK; + for( piiu = (IIU *) iiuList.node.next; + piiu; + piiu = (IIU *) piiu->node.next){ + + bytesPending = cacRingBufferReadSize(&piiu->send, FALSE); + if(bytesPending != 0){ + pending = TRUE; +# ifndef UNIX + (*piiu->sendBytes)(piiu); +# endif /*UNIX*/ + } + } + UNLOCK; + + timeout.tv_usec = LOCALTICKS; + timeout.tv_sec = 0; + } + + return ECA_NORMAL; } /* * CA_TEST_IO () * - * */ int ca_test_io() { @@ -2825,7 +3536,7 @@ void ca_busy_message(piiu) struct ioc_in_use *piiu; #endif { - struct extmsg *mptr; + struct extmsg hdr; if(!piiu){ return; @@ -2837,18 +3548,12 @@ struct ioc_in_use *piiu; if(piiu == piiuCast) return; - LOCK; - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - UNLOCK; - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); - return; - } - *mptr = nullmsg; - mptr->m_cmmd = htons(IOC_EVENTS_OFF); - CAC_ADD_MSG(piiu); + hdr = nullmsg; + hdr.m_cmmd = htons(IOC_EVENTS_OFF); + + cac_push_msg(piiu, &hdr, NULL); + piiu->send_needed = TRUE; - UNLOCK; } @@ -2863,7 +3568,7 @@ void ca_ready_message(piiu) struct ioc_in_use *piiu; #endif { - struct extmsg *mptr; + struct extmsg hdr; if(!piiu){ return; @@ -2875,44 +3580,145 @@ struct ioc_in_use *piiu; if(piiu == piiuCast) return; - LOCK; - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - UNLOCK; - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); - return; - } - *mptr = nullmsg; - mptr->m_cmmd = htons(IOC_EVENTS_ON); - CAC_ADD_MSG(piiu); - piiu->send_needed = TRUE; - UNLOCK; + hdr = nullmsg; + hdr.m_cmmd = htons(IOC_EVENTS_ON); + + cac_push_msg(piiu, &hdr, NULL); + piiu->send_needed = TRUE; } /* + * * NOOP_MSG (lock must be on) * + * now allows variable size NOOP message + * */ #ifdef __STDC__ void noop_msg(struct ioc_in_use *piiu) -#else +#else /*__STDC__*/ void noop_msg(piiu) -struct ioc_in_use *piiu; -#endif +struct ioc_in_use *piiu; +#endif /*__STDC__*/ { - struct extmsg *mptr; + struct extmsg hdr; - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); + hdr.m_cmmd = htons(IOC_NOOP); + hdr.m_type = htons(0); + hdr.m_count = htons(0); + hdr.m_cid = htons(0); + hdr.m_available = htons(0); + hdr.m_postsize = 0; + + cac_push_msg(piiu, &hdr, NULL); + + piiu->send_needed = TRUE; +} + + +/* + * ISSUE_IDENTIFY_CLIENT_LOCATION (lock must be on) + * + */ +#ifdef __STDC__ +void issue_identify_client_location(struct ioc_in_use *piiu) +#else /*__STDC__*/ +void issue_identify_client_location(piiu) +struct ioc_in_use *piiu; +#endif /*__STDC__*/ +{ + unsigned size; + struct extmsg hdr; + char *pName; + + if(!piiu){ return; } - *mptr = nullmsg; - mptr->m_cmmd = htons(IOC_NOOP); - CAC_ADD_MSG(piiu); + + /* + * dont broadcast client identification protocol + */ + if(piiu == piiuCast){ + return; + } + + /* + * prior to version 4.1 client identification + * protocol causes a disconnect - so + * dont send it in this case + */ + if(!CA_V41(CA_PROTOCOL_VERSION, piiu->minor_version_number)){ + return; + } + + /* + * allocate space in the outgoing buffer + */ + pName = ca_static->ca_pLocationName, + size = strlen(pName)+1; + hdr = nullmsg; + hdr.m_cmmd = htons(IOC_CLIENT_LOCATION); + hdr.m_postsize = size; + + cac_push_msg(piiu, &hdr, pName); + piiu->send_needed = TRUE; + + return; +} + + +/* + * ISSUE_IDENTIFY_CLIENT (lock must be on) + * + */ +#ifdef __STDC__ +void issue_identify_client(struct ioc_in_use *piiu) +#else /*__STDC__*/ +void issue_identify_client(piiu) +struct ioc_in_use *piiu; +#endif /*__STDC__*/ +{ + unsigned size; + struct extmsg hdr; + char *pName; + + if(!piiu){ + return; + } + + /* + * dont broadcast client identification protocol + */ + if(piiu == piiuCast){ + return; + } + + /* + * prior to version 4.1 client identification + * protocol causes a disconnect - so + * dont send it in this case + */ + if(!CA_V41(CA_PROTOCOL_VERSION, piiu->minor_version_number)){ + return; + } + + /* + * allocate space in the outgoing buffer + */ + pName = ca_static->ca_pUserName, + size = strlen(pName)+1; + hdr = nullmsg; + hdr.m_cmmd = htons(IOC_CLIENT_NAME); + hdr.m_postsize = size; + + cac_push_msg(piiu, &hdr, pName); + + piiu->send_needed = TRUE; + + return; } @@ -2928,7 +3734,7 @@ struct ioc_in_use *piiu; chid pchan; #endif { - struct extmsg *mptr; + struct extmsg hdr; if(!piiu){ return; @@ -2940,15 +3746,19 @@ chid pchan; if(piiu == piiuCast) return; - mptr = CAC_ALLOC_MSG(piiu, 0); - if(!mptr){ - ca_printf("%s: %s\n",__FILE__,ca_message(ECA_TOLARGE)); - return; - } - *mptr = nullmsg; - mptr->m_cmmd = htons(IOC_CLAIM_CIU); - mptr->m_cid = pchan->id.sid; - CAC_ADD_MSG(piiu); + hdr = nullmsg; + hdr.m_cmmd = htons(IOC_CLAIM_CIU); + hdr.m_cid = pchan->id.sid; + + /* + * The available field is used (abused) + * here to communicate the miner version number + * starting with CA 4.1. + */ + hdr.m_available = CA_MINOR_VERSION; + + cac_push_msg(piiu, &hdr, NULL); + piiu->send_needed = TRUE; } @@ -2961,9 +3771,9 @@ chid pchan; * */ #ifdef __STDC__ -void ca_default_exception_handler(struct exception_handler_args args) +LOCAL void ca_default_exception_handler(struct exception_handler_args args) #else -void ca_default_exception_handler(args) +LOCAL void ca_default_exception_handler(args) struct exception_handler_args args; #endif { @@ -3029,10 +3839,10 @@ int ca_defunct() */ #ifdef __STDC__ char *ca_host_name_function(chid chix) -#else +#else /*__STDC__*/ char *ca_host_name_function(chix) chid chix; -#endif +#endif /*__STDC__*/ { IIU *piiu; @@ -3055,10 +3865,10 @@ chid chix; #ifdef vxWorks #ifdef __STDC__ int ca_channel_status(int tid) -#else +#else /*__STDC__*/ int ca_channel_status(tid) int tid; -#endif +#endif /*__STDC__*/ { chid chix; IIU *piiu; @@ -3097,6 +3907,7 @@ int tid; printf("invalid channel"); break; default: + break; } printf("\n"); } @@ -3107,4 +3918,4 @@ int tid; # undef ca_static return ECA_NORMAL; } -#endif vxWorks +#endif /*vxWorks*/ diff --git a/src/ca/acctst.c b/src/ca/acctst.c index c91d5fb83..de2c8be4d 100644 --- a/src/ca/acctst.c +++ b/src/ca/acctst.c @@ -1,59 +1,65 @@ -static char *sccsId = "@(#)acctst.c 1.8\t2/19/93"; /* * CA test/debug routine */ -#if 1 -#define CA_TEST_CHNL "fredy" -#define CA_TEST_CHNL4 "fredy" -#else -#if 0 -#define CA_TEST_CHNL "ts2:ai0" -#define CA_TEST_CHNL4 "ts2:ai0" -#else -#define CA_TEST_CHNL "mv16z:ai1" -#define CA_TEST_CHNL4 "mv16z:ai1" -#endif -#endif +static char *sccsId = "$Id$"; + /* System includes */ -#if defined(UNIX) -# include -#else -# if defined(vxWorks) -# include -# include -# include -# endif -#endif +#ifdef UNIX +#include +#endif /*UNIX*/ + +#ifdef vxWorks +#include +#include +#include +#endif /*vxWorks*/ #include #include #include -/* - * #define EVENT_ROUTINE ca_test_event #define CONN_ROUTINE NULL - */ #define EVENT_ROUTINE null_event #define CONN_ROUTINE conn #define NUM 1 +#ifdef __STDC__ +int doacctst(char *pname); +void test_sync_groups(chid chix); +void multiple_sg_requests(chid chix, CA_SYNC_GID gid); +void null_event(struct event_handler_args args); +void write_event(struct event_handler_args args); +void conn(struct connection_handler_args args); +#else /*__STDC__*/ +int doacctst(); +void test_sync_groups(); +void multiple_sg_requests(); +void null_event(); +void write_event(); +void conn(); +#endif /*__STDC__*/ + #ifdef vxWorks -int spacctst() +#ifdef __STDC__ +int acctst(char *pname) +#else /*__STDC__*/ +int acctst(pname) +char *pname; +#endif /*__STDC__*/ { - int acctst(); return taskSpawn( "acctst", 200, VX_FP_TASK, 20000, - acctst, - NULL, + doacctst, + (int)pname, NULL, NULL, NULL, @@ -64,21 +70,39 @@ int spacctst() NULL, NULL); } -#endif +#endif /*vxWorks*/ + +#ifdef UNIX +#ifdef __STDC__ +main(int argc, char **argv) +#else /*__STDC__*/ +main(argc, argv) +int argc; +char **argv; +#endif /*__STDC__*/ +{ + if(argc == 2){ + doacctst(argv[1]); + } + else{ + printf("usage: %s \n", argv[0]); + } + return 0; +} +#endif /*UNIX*/ -#ifdef vxWorks -int acctst() -#else -main() -#endif +#ifdef __STDC__ +int doacctst(char *pname) +#else /*__STDC__*/ +int doacctst(pname) +char *pname; +#endif /*__STDC__*/ { chid chix1; chid chix2; chid chix3; chid chix4; - void ca_test_event(); - void null_event(); struct dbr_gr_float *ptr; struct dbr_gr_float *pgrfloat; long status; @@ -87,8 +111,6 @@ main() float *pfloat; double *pdouble; char pstring[NUM][MAX_STRING_SIZE]; - void write_event(); - void conn(); SEVCHK(ca_task_initialize(), "Unable to initialize"); @@ -96,15 +118,14 @@ main() printf("begin\n"); #ifdef VMS lib$init_timer(); -#endif +#endif /*VMS*/ ptr = (struct dbr_gr_float *) - malloc(dbr_size[DBR_GR_FLOAT] + - dbr_value_size[DBR_GR_FLOAT] * (NUM - 1)); + malloc(dbr_size_n(DBR_GR_FLOAT, NUM)); for (i = 0; i < 10; i++) { - status = ca_array_build(CA_TEST_CHNL, /* channel ASCII name */ + status = ca_array_build(pname, /* channel ASCII name */ DBR_GR_FLOAT, /* fetch external type */ NUM, /* array element cnt */ &chix3, /* ptr to chid */ @@ -113,28 +134,28 @@ main() SEVCHK(status, NULL); SEVCHK(ca_build_and_connect( - CA_TEST_CHNL4, + pname, TYPENOTCONN, 0, &chix4, NULL, - CONN_ROUTINE, + NULL, NULL), NULL); SEVCHK(ca_build_and_connect( - CA_TEST_CHNL, + pname, TYPENOTCONN, 0, &chix2, NULL, - CONN_ROUTINE, + NULL, NULL), NULL); SEVCHK(ca_build_and_connect( - CA_TEST_CHNL, + pname, TYPENOTCONN, 0, &chix1, NULL, - CONN_ROUTINE, + NULL, NULL), NULL); printf("IO status is: %s\n",ca_message(ca_test_io())); @@ -143,9 +164,10 @@ main() printf("chix2 is on %s\n", ca_host_name(chix2)); printf("chix4 is on %s\n", ca_host_name(chix4)); - status = ca_pend_io(10.0); + status = ca_pend_io(1000.0); SEVCHK(status, NULL); + printf("IO status is: %s\n",ca_message(ca_test_io())); printf("chix1 is on %s\n", ca_host_name(chix1)); @@ -153,14 +175,14 @@ main() printf("chix4 is on %s\n", ca_host_name(chix4)); SEVCHK(ca_clear_channel(chix4), NULL); - SEVCHK(ca_clear_channel(chix2), NULL); SEVCHK(ca_clear_channel(chix3), NULL); + SEVCHK(ca_clear_channel(chix2), NULL); SEVCHK(ca_clear_channel(chix1), NULL); } status = ca_array_build( - CA_TEST_CHNL, /* channel ASCII name */ + pname, /* channel ASCII name */ DBR_GR_FLOAT, /* fetch external type */ NUM, /* array element cnt */ &chix3, /* ptr to chid */ @@ -169,7 +191,7 @@ main() SEVCHK(status, NULL); SEVCHK(ca_build_and_connect( - CA_TEST_CHNL4, + pname, TYPENOTCONN, 0, &chix4, @@ -177,7 +199,7 @@ main() CONN_ROUTINE, NULL), NULL); SEVCHK(ca_build_and_connect( - CA_TEST_CHNL, + pname, TYPENOTCONN, 0, &chix2, @@ -185,7 +207,7 @@ main() CONN_ROUTINE, NULL), NULL); SEVCHK(ca_build_and_connect( - CA_TEST_CHNL, + pname, TYPENOTCONN, 0, &chix1, @@ -193,24 +215,24 @@ main() CONN_ROUTINE, NULL), NULL); - status = ca_pend_io(10.0); + status = ca_pend_io(1000.0); SEVCHK(status, NULL); if (INVALID_DB_REQ(chix1->type)) - printf("Failed to locate %s\n", CA_TEST_CHNL); + printf("Failed to locate %s\n", pname); if (INVALID_DB_REQ(chix2->type)) - printf("Failed to locate %s\n", CA_TEST_CHNL); + printf("Failed to locate %s\n", pname); if (INVALID_DB_REQ(chix3->type)) - printf("Failed to locate %s\n", CA_TEST_CHNL); + printf("Failed to locate %s\n", pname); if (INVALID_DB_REQ(chix4->type)) - printf("Failed to locate %s\n", CA_TEST_CHNL4); + printf("Failed to locate %s\n", pname); /* * SEVCHK(status,NULL); if(status == ECA_TIMEOUT) exit(); */ #ifdef VMS lib$show_timer(); -#endif +#endif /*VMS*/ pfloat = &ptr->value; for (i = 0; i < NUM; i++) @@ -218,7 +240,7 @@ main() #ifdef VMS lib$init_timer(); -#endif +#endif /*VMS*/ /* * verify we dont jam up on many uninterrupted @@ -227,24 +249,84 @@ main() printf("Performing multiple get test..."); #ifdef UNIX fflush(stdout); -#endif +#endif /*UNIX*/ { - struct dbr_ctrl_float temp; + float temp; for(i=0; i<10000; i++){ - - SEVCHK(ca_get(DBR_GR_FLOAT, chix4, &temp),NULL); + SEVCHK(ca_get(DBR_FLOAT, chix4, &temp),NULL); } - SEVCHK(ca_pend_io(200.0), NULL); + SEVCHK(ca_pend_io(2000.0), NULL); } printf("done.\n"); + /* + * verify we dont jam up on many uninterrupted requests + */ + printf("Performing multiple put test..."); +#ifdef UNIX + fflush(stdout); +#endif /*UNIX*/ + for(i=0; i<10000; i++){ + double fval = 3.3; + status = ca_put(DBR_DOUBLE, chix4, &fval); + SEVCHK(status, NULL); + } + SEVCHK(ca_pend_io(2000.0), NULL); + printf("done.\n"); + + /* + * verify we dont jam up on many uninterrupted + * solicitations + */ + printf("Performing multiple get callback test..."); +#ifdef UNIX + fflush(stdout); +#endif /*UNIX*/ + for(i=0; i<10000; i++){ + status = ca_array_get_callback( + DBR_FLOAT, + 1, + chix1, + null_event, + NULL); + + SEVCHK(status, NULL); + } + SEVCHK(ca_flush_io(), NULL); + printf("done.\n"); + + test_sync_groups(chix1); + + /* + * verify we dont jam up on many uninterrupted + * solicitations + */ + printf("Performing multiple put callback test..."); +#ifdef UNIX + fflush(stdout); +#endif /*UNIX*/ + for(i=0; i<10000; i++){ + float fval = 3.3; + status = ca_array_put_callback( + DBR_FLOAT, + 1, + chix1, + &fval, + null_event, + NULL); + + SEVCHK(status, NULL); + } + SEVCHK(ca_flush_io(), NULL); + printf("done.\n"); + /* * verify we can add many monitors at once */ printf("Performing multiple monitor test..."); #ifdef UNIX fflush(stdout); -#endif +#endif /*UNIX*/ { evid mid[1000]; float temp; @@ -258,7 +340,7 @@ main() * complete */ SEVCHK(ca_get(DBR_FLOAT,chix4,&temp),NULL); - SEVCHK(ca_pend_io(100.0),NULL); + SEVCHK(ca_pend_io(1000.0),NULL); for(i=0; i -#else -# if defined(vxWorks) +#endif +#if defined(vxWorks) # include # include -# endif #endif + #ifdef __STDC__ #include #else @@ -85,8 +85,9 @@ va_dcl pformat, args); } -#else -# if defined(vxWorks) +#endif + +#ifdef vxWorks { int logMsgArgs[6]; int i; @@ -105,9 +106,6 @@ va_dcl logMsgArgs[5]); } -# else - #### dont compile in this case #### -# endif #endif va_end(args); diff --git a/src/ca/conn.c b/src/ca/conn.c index a9bc990ab..1bf2bcdb4 100644 --- a/src/ca/conn.c +++ b/src/ca/conn.c @@ -71,8 +71,6 @@ static char *sccsId = "$Id$\t$Date$"; * retry disconnected channels * * - * NOTES: - * Lock must be applied while in this routine */ #ifdef __STDC__ void manage_conn(int silent) @@ -93,6 +91,7 @@ int silent; /* * issue connection heartbeat */ + LOCK; for( piiu = (struct ioc_in_use *) iiuList.node.next; piiu; piiu = (struct ioc_in_use *) piiu->node.next){ @@ -120,6 +119,7 @@ int silent; noop_msg(piiu); keepalive_cnt++; } + UNLOCK; if(!piiuCast){ return; @@ -140,8 +140,11 @@ int silent; } piiuCast->next_retry = current + piiuCast->retry_delay; - chix = (chid) &piiuCast->chidlist.node.next; - while(chix = (chid) chix->node.next){ + LOCK; + for( chix = (chid) piiuCast->chidlist.node.next; + chix; + chix = (chid) chix->node.next){ + build_msg(chix, DONTREPLY); retry_cnt++; @@ -150,15 +153,15 @@ int silent; retry_cnt_no_handler++; } } - + UNLOCK; if(retry_cnt){ #ifdef TRYING_MESSAGE ca_printf(" ", retry_cnt); #ifdef UNIX fflush(stdout); -#endif UNIX -#endif TRYING_MESSAGE +#endif /*UNIX*/ +#endif /*TRYING_MESSAGE*/ if(!silent && retry_cnt_no_handler){ sprintf(sprintf_buf, "%d channels outstanding", retry_cnt); @@ -174,8 +177,6 @@ int silent; * MARK_SERVER_AVAILABLE * * - * NOTES: - * Lock must be applied while in this routine * */ #ifdef __STDC__ @@ -208,6 +209,7 @@ struct in_addr *pnet_addr; */ index = ntohl(pnet_addr->s_addr); index &= BHT_INET_ADDR_MASK; + LOCK; pBHE = ca_static->ca_beaconHash[index]; while(pBHE){ if(pBHE->inetAddr.s_addr == @@ -256,6 +258,7 @@ struct in_addr *pnet_addr; } if(!netChange){ + UNLOCK; return; } } @@ -264,8 +267,9 @@ struct in_addr *pnet_addr; /* * create the hash entry */ - pBHE = (bhe *)malloc(sizeof(*pBHE)); + pBHE = (bhe *)calloc(1,sizeof(*pBHE)); if(!pBHE){ + UNLOCK; return; } @@ -311,7 +315,7 @@ struct in_addr *pnet_addr; */ { struct sockaddr_in saddr; - unsigned saddr_length = sizeof(saddr); + int saddr_length = sizeof(saddr); int status; status = getsockname( @@ -345,5 +349,6 @@ struct in_addr *pnet_addr; fflush(stdout); #endif #endif + UNLOCK; } diff --git a/src/ca/convert.c b/src/ca/convert.c index a09aca4b9..e709678bd 100644 --- a/src/ca/convert.c +++ b/src/ca/convert.c @@ -22,59 +22,169 @@ * This also provides for a cleaner seperation * of function. * joh 10-21-90 Added new DBR_XXXX types for release two + * joh 03-15-94 Added many missing types * * */ -static char *sccsId = "@(#)convert.c 1.5\t7/27/92"; +static char *sccsId = "%S% $Date$"; +#include #include #include -#ifdef vxWorks -# define memcpy(D,S,N) bcopy(S,D,N) -# define memset(D,V,N) bfill(D,N,V) -#endif +#ifdef __STDC__ + +/* + * if hton is true then it is a host to network conversion + * otherwise vise-versa + * + * net format: big endian and IEEE float + * + */ +typedef LOCAL void CACVRTFUNC( + void *pSource, + void *pDestination, + int hton, + unsigned long count); +#else /*__STDC__*/ +typedef LOCAL void CACVRTFUNC(); +#endif /*__STDC__*/ + +CACVRTFUNC cvrt_string; +CACVRTFUNC cvrt_short; +CACVRTFUNC cvrt_float; +CACVRTFUNC cvrt_enum; +CACVRTFUNC cvrt_char; +CACVRTFUNC cvrt_long; +CACVRTFUNC cvrt_double; + +CACVRTFUNC cvrt_sts_string; +CACVRTFUNC cvrt_sts_short; +CACVRTFUNC cvrt_sts_float; +CACVRTFUNC cvrt_sts_enum; +CACVRTFUNC cvrt_sts_char; +CACVRTFUNC cvrt_sts_long; +CACVRTFUNC cvrt_sts_double; + +CACVRTFUNC cvrt_time_string; +CACVRTFUNC cvrt_time_short; +CACVRTFUNC cvrt_time_float; +CACVRTFUNC cvrt_time_enum; +CACVRTFUNC cvrt_time_char; +CACVRTFUNC cvrt_time_long; +CACVRTFUNC cvrt_time_double; + +CACVRTFUNC cvrt_gr_short; +CACVRTFUNC cvrt_gr_float; +CACVRTFUNC cvrt_gr_enum; +CACVRTFUNC cvrt_gr_char; +CACVRTFUNC cvrt_gr_long; +CACVRTFUNC cvrt_gr_double; + +CACVRTFUNC cvrt_ctrl_short; +CACVRTFUNC cvrt_ctrl_float; +CACVRTFUNC cvrt_ctrl_enum; +CACVRTFUNC cvrt_ctrl_char; +CACVRTFUNC cvrt_ctrl_long; +CACVRTFUNC cvrt_ctrl_double; + +/* cvrt is (array of) (pointer to) (function returning) int */ +LOCAL CACVRTFUNC *cvrt[] + = + { + cvrt_string, + cvrt_short, + cvrt_float, + cvrt_enum, + cvrt_char, + cvrt_long, + cvrt_double, + + cvrt_sts_string, + cvrt_sts_short, + cvrt_sts_float, + cvrt_sts_enum, + cvrt_sts_char, + cvrt_sts_long, + cvrt_sts_double, + + cvrt_time_string, + cvrt_time_short, + cvrt_time_float, + cvrt_time_enum, + cvrt_time_char, + cvrt_time_long, + cvrt_time_double, + + cvrt_sts_string, /* DBR_GR_STRING identical to dbr_sts_string */ + cvrt_gr_short, + cvrt_gr_float, + cvrt_gr_enum, + cvrt_gr_char, + cvrt_gr_long, + cvrt_gr_double, + + cvrt_sts_string, /* DBR_CTRL_STRING identical to dbr_sts_string */ + cvrt_ctrl_short, + cvrt_ctrl_float, + cvrt_ctrl_enum, + cvrt_ctrl_char, + cvrt_ctrl_long, + cvrt_ctrl_double + }; static void no_cvrt(); /* - * Routine we will do later + * Native types may not match EPICS types + */ +typedef dbr_short_t short; +typedef dbr_float_t float; +typedef dbr_enum_t enum; +typedef dbr_char_t char; +typedef dbr_long_t long; +typedef dbr_double_t double; +#define dbr_ntohs(A) ntohs(A) +#define dbr_ntohl(A) ntohl(A) +#define dbr_htons(A) htons(A) +#define dbr_htonl(A) htonl(A) + + + +/* + * CVRT_STRING() + * * * * */ -static void no_cvrt() +#ifdef __STDC__ +void cvrt_string( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +void cvrt_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T */ +unsigned long num; /* number of values */ +#endif { - ca_printf("Sorry, conversion for that type currently not implemented\n"); - exit(); + dbr_char_t *pSrc = s; + dbr_char_t *pDest = d; + + if(num == 1){ + strcpy(pDest, pSrc); + } + else{ + memcpy(pDest, pSrc, num*MAXSTRINGSIZE); + } } -cvrt_sts_char() {no_cvrt();} -cvrt_sts_long() {no_cvrt();} -cvrt_sts_double() {no_cvrt();} - -cvrt_time_string() {no_cvrt();} -cvrt_time_short() {no_cvrt();} -cvrt_time_float() {no_cvrt();} -cvrt_time_enum() {no_cvrt();} -cvrt_time_char() {no_cvrt();} -cvrt_time_long() {no_cvrt();} -cvrt_time_double() {no_cvrt();} - -cvrt_gr_char() {no_cvrt();} -cvrt_gr_double() {no_cvrt();} -cvrt_gr_long() {no_cvrt();} -cvrt_gr_string() {no_cvrt();} -cvrt_gr_enum() {no_cvrt();} - -cvrt_ctrl_char() {no_cvrt();} -cvrt_ctrl_long() {no_cvrt();} -cvrt_ctrl_string() {no_cvrt();} -cvrt_ctrl_double() {no_cvrt();} - - - /* @@ -85,26 +195,27 @@ cvrt_ctrl_double() {no_cvrt();} * */ #ifdef __STDC__ -cvrt_short( -short *s, /* source */ -short *d, /* destination */ +void cvrt_short( +void *s, /* source */ +void *d, /* destination */ int encode, /* cvrt VAX to IEEE if T */ -int num /* number of values */ +unsigned long num /* number of values */ ) #else -cvrt_short(s,d,encode,num) -short *s; /* source */ -short *d; /* destination */ +void cvrt_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ int encode; /* cvrt VAX to IEEE if T */ -int num; /* number of values */ +unsigned long num; /* number of values */ #endif { - unsigned int i; + dbr_short_t *pSrc = s; + dbr_short_t *pDest = d; + unsigned long i; for(i=0; istatus = ntohs(s->status); - d->severity = ntohs(s->severity); - if (num == 1) /* if single value */ - strcpy(d->value,s->value); - else - memcpy(d->value,s->value,(MAX_STRING_SIZE * num)); + /* convert ieee to vax format or vax to ieee */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + if (num == 1) /* if single value */ + strcpy(pDest->value, pSrc->value); + else + memcpy(pDest->value, pSrc->value, (MAX_STRING_SIZE * num)); - return 1; } @@ -369,47 +454,35 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -cvrt_sts_short( -struct dbr_sts_int *s, /* source */ -struct dbr_sts_int *d, /* destination */ -int encode, /* if true; vax to ieee */ -int num /* number of values */ +void cvrt_sts_short( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -cvrt_sts_short(s,d,encode,num) -struct dbr_sts_int *s; /* source */ -struct dbr_sts_int *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +void cvrt_sts_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - short *sval_ptr,*dval_ptr; /* ptrs to source, destination */ + struct dbr_sts_int *pSrc = s; + struct dbr_sts_int *pDest = d; - /* convert vax to ieee or ieee to vax format -- same code*/ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); - if (num == 1) /* single value */ - d->value = ntohs(s->value); - else /* array chan-- multiple pts */ - { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0; i < num; i++){ - *dval_ptr = ntohs(*sval_ptr); - sval_ptr++; - dval_ptr++; - } - } - - - return 1; + if (num == 1) /* single value */ + pDest->value = dbr_ntohs(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_short(&pSrc->value, &pDest->value, encode, num); + } } - - - /**************************************************************************** ** cvrt_sts_float(s,d) ** struct dbr_sts_float *s pointer to source struct @@ -425,62 +498,65 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -cvrt_sts_float( -struct dbr_sts_float *s, /* source */ -struct dbr_sts_float *d, /* destination */ -int encode, /* it true, vax to ieee */ -int num /* number of values */ +void cvrt_sts_float( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -cvrt_sts_float(s,d,encode,num) -struct dbr_sts_float *s; /* source */ -struct dbr_sts_float *d; /* destination */ -int encode; /* it true, vax to ieee */ -int num; /* number of values */ +void cvrt_sts_float(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - float *sval_ptr,*dval_ptr; + struct dbr_sts_float *pSrc = s; + struct dbr_sts_float *pDest = d; - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); - if(encode) /* vax to ieee convert */ - if(num == 1){ - htonf(&s->value, &d->value); - } - else - { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - htonf(sval_ptr,dval_ptr); - sval_ptr++; - dval_ptr++; - } - } - - else /* ieee to vax convert */ - if(num == 1){ - ntohf(&s->value,&d->value); - } - else - { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - ntohf(sval_ptr,dval_ptr); - dval_ptr++; - sval_ptr++; - } - } - - return 1; + cvrt_float(&pSrc->value, &pDest->value, encode, num); } +/**************************************************************************** +** cvrt_sts_double(s,d) +** +** if encode +** converts struct in VAX format to ieee format +** else +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ +#ifdef __STDC__ +LOCAL void cvrt_sts_double( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_sts_double(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_sts_double *pSrc = s; + struct dbr_sts_double *pDest = d; + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + + cvrt_double(&pSrc->value, &pDest->value, encode, num); +} + + /**************************************************************************** ** cvrt_sts_enum(s,d) ** struct dbr_sts_enum *s pointer to source struct @@ -494,41 +570,37 @@ int num; /* number of values */ ** ****************************************************************************/ -cvrt_sts_enum(s,d,encode,num) -struct dbr_sts_enum *s; /* source */ -struct dbr_sts_enum *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +#ifdef __STDC__ +LOCAL void cvrt_sts_enum( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_sts_enum(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T */ +unsigned long num; /* number of values */ +#endif { - register i; - short *dval_ptr,*sval_ptr; + struct dbr_sts_enum *pSrc = s; + struct dbr_sts_enum *pDest = d; - /* convert vax to ieee or ieee to vax --same code */ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); - if (num == 1) - d->value = ntohs(s->value); - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0; i < num; i++){ - *dval_ptr = ntohs(*sval_ptr); - dval_ptr++; - sval_ptr++; - } - } - return 1; + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + memcpy(&pDest->strs, &pSrc->strs, sizeof(pDest->strs)); + if (num == 1) + d->value = dbr_ntohs(s->value); + else { + cvrt_enum(&pSrc->value,&pDest->value,encode,num) + } } - - /**************************************************************************** -** cvrt_gr_short(s,d) -** struct dbr_gr_int *s pointer to source struct -** struct dbr_gr_int *d pointer to destination struct -** int encode; boolean, if true vax to ieee -** else ieee to vax +** cvrt_gr_short() ** ** converts fields of struct in IEEE format to fields with VAX format ** or @@ -537,54 +609,244 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -int cvrt_gr_short( -struct dbr_gr_int *s, /* source */ -struct dbr_gr_int *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ +LOCAL void cvrt_gr_short( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -int cvrt_gr_short(s,d,encode,num) -struct dbr_gr_int *s; /* source */ -struct dbr_gr_int *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +LOCAL void cvrt_gr_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - short *sval_ptr,*dval_ptr; + struct dbr_gr_int *pSrc = s; + struct dbr_gr_int *pDest = d; - /* convert ieee to vax or vax to ieee -- same code */ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); - strcpy(d->units,s->units); + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); - d->upper_disp_limit = ntohs(s->upper_disp_limit); - d->lower_disp_limit = ntohs(s->lower_disp_limit); - d->upper_alarm_limit = ntohs(s->upper_alarm_limit); - d->upper_warning_limit = ntohs(s->upper_warning_limit); - d->lower_alarm_limit = ntohs(s->lower_alarm_limit); - d->lower_warning_limit = ntohs(s->lower_warning_limit); + pDest->upper_disp_limit = dbr_ntohs(pSrc->upper_disp_limit); + pDest->lower_disp_limit = dbr_ntohs(pSrc->lower_disp_limit); + pDest->upper_alarm_limit = dbr_ntohs(pSrc->upper_alarm_limit); + pDest->upper_warning_limit = dbr_ntohs(pSrc->upper_warning_limit); + pDest->lower_alarm_limit = dbr_ntohs(pSrc->lower_alarm_limit); + pDest->lower_warning_limit = dbr_ntohs(pSrc->lower_warning_limit); - if (num == 1) - d->value = ntohs(s->value); - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - *dval_ptr = ntohs(*sval_ptr); - dval_ptr++; - sval_ptr++; + if (num == 1) + pDest->value = dbr_ntohs(pSrc->value); + else { + cvrt_short(&pSrc->value, &pDest->value, encode,num); } - } - - - return 1; } +/**************************************************************************** +** cvrt_gr_char() +** +** converts fields of struct in IEEE format to fields with VAX format +** or +** converts fields of struct in VAX format to fields with IEEE format +** +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_gr_char( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else /*__STDC__*/ +LOCAL void cvrt_gr_char(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif /*__STDC__*/ +{ + struct dbr_gr_char *pSrc = s; + struct dbr_gr_char *pDest = d; + + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); + + pDest->upper_disp_limit = pSrc->upper_disp_limit; + pDest->lower_disp_limit = pSrc->lower_disp_limit; + pDest->upper_alarm_limit = pSrc->upper_alarm_limit; + pDest->upper_warning_limit = pSrc->upper_warning_limit; + pDest->lower_alarm_limit = pSrc->lower_alarm_limit; + pDest->lower_warning_limit = pSrc->lower_warning_limit; + + if (num == 1) + pDest->value = pSrc->value; + else { + memcpy(&pDest->value, &pSrc->value, num); + } +} + + +/**************************************************************************** +** cvrt_gr_long() +** +** converts fields of struct in IEEE format to fields with VAX format +** or +** converts fields of struct in VAX format to fields with IEEE format +** +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_gr_long( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_gr_long(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_gr_long *pSrc = s; + struct dbr_gr_long *pDest = d; + + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); + + pDest->upper_disp_limit = dbr_ntohl(pSrc->upper_disp_limit); + pDest->lower_disp_limit = dbr_ntohl(pSrc->lower_disp_limit); + pDest->upper_alarm_limit = dbr_ntohl(pSrc->upper_alarm_limit); + pDest->upper_warning_limit = dbr_ntohl(pSrc->upper_warning_limit); + pDest->lower_alarm_limit = dbr_ntohl(pSrc->lower_alarm_limit); + pDest->lower_warning_limit = dbr_ntohl(pSrc->lower_warning_limit); + + if (num == 1) + pDest->value = dbr_ntohl(pSrc->value); + else { + cvrt_long(&pSrc->value, &pDest->value, encode, num); + } +} + + +/**************************************************************************** +** cvrt_gr_enum(s,d) +** +** if encode +** converts struct in VAX format to ieee format +** else +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_gr_enum( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_gr_enum(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_gr_enum *pSrc = s; + struct dbr_gr_enum *pDest = d; + + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->no_str = dbr_ntohs(pSrc->no_str); + memcpy(pDest->strs,pSrc->strs,sizeof(pSrc->strs)); + + if (num == 1) /* single value */ + pDest->value = dbr_ntohs(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_enum(&(pSrc->value), &(pDest->value), encode, num); + } +} + + +/**************************************************************************** +** cvrt_gr_double(s,d) +** +** if encode +** converts struct in VAX format to ieee format +** else +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_gr_double( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_gr_double(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_gr_double *pSrc = s; + struct dbr_gr_double *pDest = d; + + /* these are same for vax to ieee or ieee to vax */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->precision = dbr_ntohs(pSrc->precision); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); + + if (encode) /* vax to ieee convert */ + { + if (num == 1){ + htond(&s->value, &d->value); + } + else { + cvrt_double(&pSrc->value, &pDest->value, encode,num); + } + htond(&pSrc->upper_disp_limit,&pDest->upper_disp_limit); + htond(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + htond(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + htond(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + htond(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + htond(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + } + else /* ieee to vax convert */ + { + if (num == 1){ + ntohd(&pSrc->value, &pDest->value); + } + else { + cvrt_double(&pSrc->value, &pDest->value, encode,num); + } + ntohd(&pSrc->upper_disp_limit,&pDest->upper_disp_limit); + ntohd(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + ntohd(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + ntohd(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + ntohd(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + ntohd(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + } +} + /**************************************************************************** ** cvrt_gr_float(s,d) ** struct dbr_gr_float *d pointer to destination struct @@ -599,74 +861,59 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -int cvrt_gr_float( -struct dbr_gr_float *s, /* source */ -struct dbr_gr_float *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ +LOCAL void cvrt_gr_float( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -int cvrt_gr_float(s,d,encode,num) -struct dbr_gr_float *s; /* source */ -struct dbr_gr_float *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +LOCAL void cvrt_gr_float(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - float *sval_ptr,*dval_ptr; + struct dbr_gr_float *pSrc = s; + struct dbr_gr_float *pDest = d; - /* these are same for vax to ieee or ieee to vax */ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); - d->precision = ntohs(s->precision); - strcpy(d->units,s->units); + /* these are same for vax to ieee or ieee to vax */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->precision = dbr_ntohs(pSrc->precision); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); - if (encode) /* vax to ieee convert */ - { - if (num == 1){ - htonf(&s->value, &d->value); - } - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - htonf(sval_ptr,dval_ptr); - dval_ptr++; - sval_ptr++; - } - } - htonf(&s->upper_disp_limit,&d->upper_disp_limit); - htonf(&s->lower_disp_limit, &d->lower_disp_limit); - htonf(&s->upper_alarm_limit, &d->upper_alarm_limit); - htonf(&s->upper_warning_limit, &d->upper_warning_limit); - htonf(&s->lower_alarm_limit, &d->lower_alarm_limit); - htonf(&s->lower_warning_limit, &d->lower_warning_limit); - } - else /* ieee to vax convert */ - { - if (num == 1){ - ntohf(&s->value, &d->value); - } - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - ntohf(sval_ptr,dval_ptr); - dval_ptr++; - sval_ptr++; - } - } - ntohf(&s->upper_disp_limit,&d->upper_disp_limit); - ntohf(&s->lower_disp_limit, &d->lower_disp_limit); - ntohf(&s->upper_alarm_limit, &d->upper_alarm_limit); - ntohf(&s->upper_warning_limit, &d->upper_warning_limit); - ntohf(&s->lower_alarm_limit, &d->lower_alarm_limit); - ntohf(&s->lower_warning_limit, &d->lower_warning_limit); - } - - - return 1; + if (encode) /* vax to ieee convert */ + { + if (num == 1){ + htonf(&s->value, &d->value); + } + else { + cvrt_float(&pSrc->value, &pDest->value, encode,num); + } + htonf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit); + htonf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + htonf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + htonf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + htonf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + htonf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + } + else /* ieee to vax convert */ + { + if (num == 1){ + ntohf(&pSrc->value, &pDest->value); + } + else { + cvrt_float(&pSrc->value, &pDest->value, encode,num); + } + ntohf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit); + ntohf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + ntohf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + ntohf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + ntohf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + ntohf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + } } @@ -686,62 +933,212 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -int cvrt_ctrl_short( -struct dbr_ctrl_int *s, /* source */ -struct dbr_ctrl_int *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ +LOCAL void cvrt_ctrl_short( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -int cvrt_ctrl_short(s,d,encode,num) -struct dbr_ctrl_int *s; /* source */ -struct dbr_ctrl_int *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +LOCAL void cvrt_ctrl_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - short *sval_ptr,*dval_ptr; + struct dbr_ctrl_int *pSrc = s; + struct dbr_ctrl_int *pDest = d; - /* vax to ieee or ieee to vax -- same code */ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); - strcpy(d->units,s->units); + /* vax to ieee or ieee to vax -- same code */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); - d->upper_disp_limit = ntohs(s->upper_disp_limit); - d->lower_disp_limit = ntohs(s->lower_disp_limit); - d->upper_alarm_limit = ntohs(s->upper_alarm_limit); - d->upper_warning_limit = ntohs(s->upper_warning_limit); - d->lower_alarm_limit = ntohs(s->lower_alarm_limit); - d->lower_warning_limit = ntohs(s->lower_warning_limit); - d->lower_ctrl_limit = ntohs(s->lower_ctrl_limit); - d->upper_ctrl_limit = ntohs(s->upper_ctrl_limit); + pDest->upper_disp_limit = dbr_ntohs(pSrc->upper_disp_limit); + pDest->lower_disp_limit = dbr_ntohs(pSrc->lower_disp_limit); + pDest->upper_alarm_limit = dbr_ntohs(pSrc->upper_alarm_limit); + pDest->upper_warning_limit = dbr_ntohs(pSrc->upper_warning_limit); + pDest->lower_alarm_limit = dbr_ntohs(pSrc->lower_alarm_limit); + pDest->lower_warning_limit = dbr_ntohs(pSrc->lower_warning_limit); + pDest->lower_ctrl_limit = dbr_ntohs(pSrc->lower_ctrl_limit); + pDest->upper_ctrl_limit = dbr_ntohs(pSrc->upper_ctrl_limit); - if (num == 1) - d->value = ntohs(s->value); - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - *dval_ptr = ntohs(*sval_ptr); - dval_ptr++; - sval_ptr++; - } - } - + if (num == 1) + pDest->value = dbr_ntohs(pSrc->value); + else { + cvrtshort(&pSrc->value, &pDest->value, encode, num); + } +} - return 1; +/**************************************************************************** +** cvrt_ctrl_long(s,d) +** +** converts fields of struct in IEEE format to fields with VAX format +** or +** converts fields of struct in VAX format to fields with IEEE format +** +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_ctrl_long( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_ctrl_long(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_ctrl_long *pSrc = s; + struct dbr_ctrl_long *pDest = d; + + /* vax to ieee or ieee to vax -- same code */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); + + pDest->upper_disp_limit = dbr_ntohl(pSrc->upper_disp_limit); + pDest->lower_disp_limit = dbr_ntohl(pSrc->lower_disp_limit); + pDest->upper_alarm_limit = dbr_ntohl(pSrc->upper_alarm_limit); + pDest->upper_warning_limit = dbr_ntohl(pSrc->upper_warning_limit); + pDest->lower_alarm_limit = dbr_ntohl(pSrc->lower_alarm_limit); + pDest->lower_warning_limit = dbr_ntohl(pSrc->lower_warning_limit); + pDest->lower_ctrl_limit = dbr_ntohl(pSrc->lower_ctrl_limit); + pDest->upper_ctrl_limit = dbr_ntohl(pSrc->upper_ctrl_limit); + + if (num == 1) + pDest->value = dbr_ntohl(pSrc->value); + else { + cvrtlong(&pSrc->value, &pDest->value, encode, num); + } +} + +/**************************************************************************** +** cvrt_ctrl_short(s,d) +** +** converts fields of struct in IEEE format to fields with VAX format +** or +** converts fields of struct in VAX format to fields with IEEE format +** +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_ctrl_char( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_ctrl_char(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_ctrl_char *pSrc = s; + struct dbr_ctrl_char *pDest = d; + + /* vax to ieee or ieee to vax -- same code */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + + pDest->upper_disp_limit = pSrc->upper_disp_limit; + pDest->lower_disp_limit = pSrc->lower_disp_limit; + pDest->upper_alarm_limit = pSrc->upper_alarm_limit; + pDest->upper_warning_limit = pSrc->upper_warning_limit; + pDest->lower_ctrl_limit = pSrc->lower_ctrl_limit; + pDest->upper_ctrl_limit = pSrc->upper_ctrl_limit; + + if (num == 1) + pDest->value = pSrc->value; + else { + memcpy(&pDest->value, &pSrc->value, num); + } } +/**************************************************************************** +** cvrt_ctrl_double(s,d) +** +** if encode +** converts struct in VAX format to ieee format +** else +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_ctrl_double( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_ctrl_double(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_ctrl_double *pSrc = s; + struct dbr_ctrl_double *pDest = d; + + /* these are the same for ieee to vaax or vax to ieee */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->precision = dbr_ntohs(pSrc->precision); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); + if (encode) /* vax to ieee convert */ + { + if (num == 1){ + htond(&pSrc->value, &pDest->value); + } + else { + cvrt_double(&pSrc->value, &pDest->value, encode, num); + } + htond(&pSrc->upper_disp_limit,&pDest->upper_disp_limit); + htond(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + htond(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + htond(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + htond(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + htond(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + htond(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit); + htond(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit); + } + else /* ieee to vax convert */ + { + if (num == 1){ + ntohd(&pSrc->value, &pDest->value); + } + else { + cvrt_double(&pSrc->value, &pDest->value, encode, num); + } + ntohd(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + ntohd(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + ntohd(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + ntohd(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + ntohd(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + ntohd(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit); + ntohd(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit); + } + +} + + /**************************************************************************** ** cvrt_ctrl_float(s,d) -** struct dbr_ctrl_float *s pointer to source struct -** struct dbr_ctrl_float *d pointer to destination struct -** int encode; boolean, if true vax to ieee -** else ieee to vax ** ** if encode ** converts struct in VAX format to ieee format @@ -751,85 +1148,68 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -int cvrt_ctrl_float( -struct dbr_ctrl_float *s, /* source */ -struct dbr_ctrl_float *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ +LOCAL void cvrt_ctrl_float( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -int cvrt_ctrl_float(s,d,encode,num) -struct dbr_ctrl_float *s; /* source */ -struct dbr_ctrl_float *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +LOCAL void cvrt_ctrl_float(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - float *sval_ptr,*dval_ptr; + struct dbr_ctrl_float *pSrc = s; + struct dbr_ctrl_float *pDest = d; - /* these are the same for ieee to vaax or vax to ieee */ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); - d->precision = ntohs(s->precision); - strcpy(d->units,s->units); - if (encode) /* vax to ieee convert */ - { - if (num == 1){ - htonf(&s->value, &d->value); - } - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - htonf(sval_ptr,dval_ptr); - dval_ptr++; - sval_ptr++; - } - } - htonf(&s->upper_disp_limit,&d->upper_disp_limit); - htonf(&s->lower_disp_limit, &d->lower_disp_limit); - htonf(&s->upper_alarm_limit, &d->upper_alarm_limit); - htonf(&s->upper_warning_limit, &d->upper_warning_limit); - htonf(&s->lower_alarm_limit, &d->lower_alarm_limit); - htonf(&s->lower_warning_limit, &d->lower_warning_limit); - htonf(&s->lower_ctrl_limit, &d->lower_ctrl_limit); - htonf(&s->upper_ctrl_limit, &d->upper_ctrl_limit); - } - else /* ieee to vax convert */ - { - if (num == 1){ - ntohf(&s->value, &d->value); - } - else { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0;i < num; i++){ - ntohf(sval_ptr,dval_ptr); - dval_ptr++; - sval_ptr++; - } - } - ntohf(&s->lower_disp_limit, &d->lower_disp_limit); - ntohf(&s->upper_alarm_limit, &d->upper_alarm_limit); - ntohf(&s->upper_warning_limit, &d->upper_warning_limit); - ntohf(&s->lower_alarm_limit, &d->lower_alarm_limit); - ntohf(&s->lower_warning_limit, &d->lower_warning_limit); - ntohf(&s->lower_ctrl_limit, &d->lower_ctrl_limit); - ntohf(&s->upper_ctrl_limit, &d->upper_ctrl_limit); - } + /* these are the same for ieee to vaax or vax to ieee */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->precision = dbr_ntohs(pSrc->precision); + memcpy(pDest->units,pSrc->units,sizeof(pSrc->units)); + if (encode) /* vax to ieee convert */ + { + if (num == 1){ + htonf(&pSrc->value, &pDest->value); + } + else { + cvrt_float(&pSrc->value, &pDest->value, encode, num); + } + htonf(&pSrc->upper_disp_limit,&pDest->upper_disp_limit); + htonf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + htonf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + htonf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + htonf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + htonf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + htonf(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit); + htonf(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit); + } + else /* ieee to vax convert */ + { + if (num == 1){ + ntohf(&pSrc->value, &pDest->value); + } + else { + cvrt_float(&pSrc->value, &pDest->value, encode, num); + } + ntohf(&pSrc->lower_disp_limit, &pDest->lower_disp_limit); + ntohf(&pSrc->upper_alarm_limit, &pDest->upper_alarm_limit); + ntohf(&pSrc->upper_warning_limit, &pDest->upper_warning_limit); + ntohf(&pSrc->lower_alarm_limit, &pDest->lower_alarm_limit); + ntohf(&pSrc->lower_warning_limit, &pDest->lower_warning_limit); + ntohf(&pSrc->lower_ctrl_limit, &pDest->lower_ctrl_limit); + ntohf(&pSrc->upper_ctrl_limit, &pDest->upper_ctrl_limit); + } - - return 1; } + /**************************************************************************** ** cvrt_ctrl_enum(s,d) -** struct dbr_ctrl_enum *s pointer to source struct -** struct dbr_ctrl_enum *d pointer to destination struct -** int encode; boolean, if true vax to ieee -** else ieee to vax ** ** if encode ** converts struct in VAX format to ieee format @@ -839,41 +1219,482 @@ int num; /* number of values */ ****************************************************************************/ #ifdef __STDC__ -cvrt_ctrl_enum( -struct dbr_ctrl_enum *s, /* source */ -struct dbr_ctrl_enum *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ +LOCAL void cvrt_ctrl_enum( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ ) #else -cvrt_ctrl_enum(s,d,encode,num) -struct dbr_ctrl_enum *s; /* source */ -struct dbr_ctrl_enum *d; /* destination */ -int encode; /* if true, vax to ieee */ -int num; /* number of values */ +LOCAL void cvrt_ctrl_enum(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ #endif { - register i; - short *sval_ptr,*dval_ptr; + struct dbr_ctrl_enum *pSrc = s; + struct dbr_ctrl_enum *pDest = d; - /* vax to ieee or ieee to vax -- same code */ - d->status = ntohs(s->status); - d->severity = ntohs(s->severity); - d->no_str = ntohs(s->no_str); - memcpy(d->strs,s->strs,sizeof(s->strs)); + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->no_str = dbr_ntohs(pSrc->no_str); + memcpy(pDest->strs,pSrc->strs,sizeof(pSrc->strs)); - if (num == 1) /* single value */ - d->value = ntohs(s->value); - else /* array chan-- multiple pts */ - { - sval_ptr = &(s->value); - dval_ptr = &(d->value); - for (i = 0; i < num; i++){ - *dval_ptr = ntohs(*sval_ptr); - dval_ptr++; - sval_ptr++; + if (num == 1) /* single value */ + pDest->value = dbr_ntohs(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_enum(&(pSrc->value), &(pDest->value), encode, num); } - } - - return 1; } + + +/**************************************************************************** +** cvrt_sts_char(s,d) +** struct dbr_sts_int *s pointer to source struct +** struct dbr_sts_int *d pointer to destination struct +** int encode; boolean, if true vax to ieee +** else ieee to vax +** +** converts fields ofstruct in VAX format to ieee format +** or +** converts fields of struct in IEEE format to fields with VAX +** format +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_sts_char( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_sts_char(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_sts_char *pSrc = s; + struct dbr_sts_char *pDest = d; + + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + + if (num == 1) /* single value */ + pDest->value = pSrc->value; + else /* array chan-- multiple pts */ + { + memcpy(&pDest->value, &pSrc->value, num); + } +} + + +/**************************************************************************** +** cvrt_sts_long(s,d) +** +** converts fields ofstruct in VAX format to ieee format +** or +** converts fields of struct in IEEE format to fields with VAX +** format +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_sts_long( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_sts_long(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_sts_long *pSrc = s; + struct dbr_sts_long *pDest = d; + + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + + if (num == 1) /* single value */ + pDest->value = dbr_ntohl(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_long(&pDest->value, &pSrc->value, encode, num); + } +} + + + +/**************************************************************************** +** cvrt_time_string(s,d) +** +** converts fields of struct in VAX format to IEEE format +** or +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_string( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_time_string(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_string *pSrc = s; + struct dbr_time_string *pDest = d; + + /* convert ieee to vax format or vax to ieee */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + if (num == 1) /* if single value */ + strcpy(pDest->value, pSrc->value); + else + memcpy(pDest->value, pSrc->value, (MAX_STRING_SIZE * num)); + +} + + +/**************************************************************************** +** cvrt_time_short(s,d) +** +** converts fields ofstruct in VAX format to ieee format +** or +** converts fields of struct in IEEE format to fields with VAX +** format +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_short( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_time_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_int *pSrc = s; + struct dbr_time_int *pDest = d; + + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + if (num == 1) /* single value */ + pDest->value = dbr_ntohs(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_short(&pSrc->value, &pDest->value, encode, num); + } +} + + +/**************************************************************************** +** cvrt_time_float(s,d) +** +** if encode +** converts struct in VAX format to ieee format +** else +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_float( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +cvrt_time_float(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_float *pSrc = s; + struct dbr_time_float *pDest = d; + + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + cvrt_float(&pSrc->value, &pDest->value, encode, num); +} + + +/**************************************************************************** +** cvrt_time_double(s,d) +** +** if encode +** converts struct in VAX format to ieee format +** else +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_double( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +cvrt_time_double(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_double *pSrc = s; + struct dbr_time_double *pDest = d; + + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + cvrt_double(&pSrc->value, &pDest->value, encode, num); +} + + + +/**************************************************************************** +** cvrt_time_string(s,d) +** +** converts fields of struct in VAX format to IEEE format +** or +** converts fields of struct in IEEE format to fields with VAX +** format; +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_string( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_time_string(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_string *pSrc = s; + struct dbr_time_string *pDest = d; + + /* convert ieee to vax format or vax to ieee */ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + if (num == 1) /* if single value */ + strcpy(pDest->value, pSrc->value); + else + memcpy(pDest->value, pSrc->value, MAX_STRING_SIZE*num); + +} + + +/**************************************************************************** +** cvrt_time_short(s,d) +** +** converts fields ofstruct in VAX format to ieee format +** or +** converts fields of struct in IEEE format to fields with VAX +** format +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_short( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_time_short(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_int *pSrc = s; + struct dbr_time_int *pDest = d; + + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + if (num == 1) /* single value */ + pDest->value = dbr_ntohs(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_short(&pSrc->value, &pDest->value, encode, num); + } +} + + + +/**************************************************************************** +** cvrt_time_enum(s,d) +** +** converts fields of struct in IEEE format to fields with VAX format +** or +** converts fields of struct in VAX format to fields with IEEE format +** +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_enum( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else /*__STDC__*/ +LOCAL void cvrt_time_enum(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif /*__STDC__*/ +{ + struct dbr_time_enum *pSrc = s; + struct dbr_time_enum *pDest = d; + + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + if (num == 1) + d->value = dbr_ntohs(s->value); + else { + cvrt_enum(&pSrc->value,&pDest->value,encode,num) + } +} + + +/**************************************************************************** +** cvrt_sts_char(s,d) +** +** converts fields ofstruct in VAX format to ieee format +** or +** converts fields of struct in IEEE format to fields with VAX +** format +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_char( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_time_char(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_char *pSrc = s; + struct dbr_time_char *pDest = d; + + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + if (num == 1) /* single value */ + pDest->value = pSrc->value; + else /* array chan-- multiple pts */ + { + memcpy(&pDest->value, &pSrc->value, num); + } +} + +/**************************************************************************** +** cvrt_time_long(s,d) +** +** converts fields ofstruct in VAX format to ieee format +** or +** converts fields of struct in IEEE format to fields with VAX +** format +****************************************************************************/ + +#ifdef __STDC__ +LOCAL void cvrt_time_long( +void *s, /* source */ +void *d, /* destination */ +int encode, /* cvrt VAX to IEEE if T */ +unsigned long num /* number of values */ +) +#else +LOCAL void cvrt_time_long(s,d,encode,num) +void *s; /* source */ +void *d; /* destination */ +int encode; /* cvrt VAX to IEEE if T*/ +unsigned long num; /* number of values */ +#endif +{ + struct dbr_time_long *pSrc = s; + struct dbr_time_long *pDest = d; + + /* convert vax to ieee or ieee to vax format -- same code*/ + pDest->status = dbr_ntohs(pSrc->status); + pDest->severity = dbr_ntohs(pSrc->severity); + pDest->stamp.secPastEpoch = dbr_ntohl(pSrc->stamp.secPastEpoch); + pDest->stamp.nsec = dbr_ntohl(pSrc->stamp.nsec); + + if (num == 1) /* single value */ + pDest->value = dbr_ntohl(pSrc->value); + else /* array chan-- multiple pts */ + { + cvrt_long(&pDest->value, &pSrc->value, encode, num); + } +} + + diff --git a/src/ca/flow_control.c b/src/ca/flow_control.c index 311ce4dc5..3177e19cc 100644 --- a/src/ca/flow_control.c +++ b/src/ca/flow_control.c @@ -86,6 +86,8 @@ struct ioc_in_use *piiu; register int status; register int busy = piiu->client_busy; + LOCK; + /* * use of the additional system call here does not * seem to slow things down appreciably @@ -94,8 +96,7 @@ struct ioc_in_use *piiu; FIONREAD, (int)&nbytes); if (status < 0) { - LOCK; - close_ioc(piiu); + piiu->conn_up = FALSE; UNLOCK; return; } @@ -111,7 +112,7 @@ struct ioc_in_use *piiu; MAX_CONTIGUOUS_MSG_COUNT) { piiu->client_busy = TRUE; ca_busy_message(piiu); -# if DEBUG +# ifdef DEBUG printf("fc on\n"); # endif } @@ -126,5 +127,7 @@ struct ioc_in_use *piiu; } } + UNLOCK; + return; } diff --git a/src/ca/iocinf.c b/src/ca/iocinf.c index 6937028c8..274581dfb 100644 --- a/src/ca/iocinf.c +++ b/src/ca/iocinf.c @@ -42,6 +42,9 @@ /* 091493 joh init send retry count when each recv and at */ /* at connect */ /* 102993 joh toggle set sock opt to set */ +/* 021794 joh turn on SO_REUSEADDR only after the test for */ +/* address in use so that test works on UNIX */ +/* kernels that support multicast */ /* */ /*_begin */ /************************************************************************/ @@ -72,7 +75,7 @@ static char *sccsId = "$Id$\t$Date$"; /* Allocate storage for global variables in this module */ #define CA_GLBLSOURCE -#if defined(VMS) +#ifdef VMS # include # include # include @@ -82,15 +85,16 @@ static char *sccsId = "$Id$\t$Date$"; # include # include # include -# if defined(UCX) /* GeG 09-DEC-1992 */ +# ifdef UCX /* GeG 09-DEC-1992 */ # include # include # else # include # include # endif -#else -# if defined(UNIX) +#endif /*VMS*/ + +#ifdef UNIX # include # include # include @@ -98,8 +102,10 @@ static char *sccsId = "$Id$\t$Date$"; # include # include # include -# else -# if defined(vxWorks) +# include +#endif /*UNIX*/ + +#ifdef vxWorks # include # include # include @@ -118,56 +124,63 @@ static char *sccsId = "$Id$\t$Date$"; # include # include # include -# endif -# endif -#endif +# include +#endif /*vxWorks*/ #ifdef vxWorks #include #endif -#include #include -#include #include #ifdef UNIX static struct timeval notimeout = {0,0}; -#endif +#endif /*UNIX*/ #ifdef __STDC__ LOCAL void tcp_recv_msg(struct ioc_in_use *piiu); LOCAL void cac_flush_internal(); -LOCAL int cac_send_msg_piiu(struct ioc_in_use *piiu); +LOCAL void cac_send_msg_piiu(struct ioc_in_use *piiu); LOCAL void notify_ca_repeater(); -LOCAL void recv_msg(struct ioc_in_use *piiu); LOCAL void udp_recv_msg(struct ioc_in_use *piiu); +#ifdef JUNKYARD LOCAL void clean_iiu_list(); +#endif #ifdef VMS LOCAL void vms_recv_msg_ast(struct ioc_in_use *piiu); -#endif - -LOCAL int -create_net_chan( +#endif /*VMS*/ +LOCAL void ca_process_tcp(struct ioc_in_use *piiu); +LOCAL void ca_process_udp(struct ioc_in_use *piiu); +LOCAL void ca_process_input_queue(); +LOCAL void close_ioc(struct ioc_in_use *piiu); +LOCAL int create_net_chan( struct ioc_in_use **ppiiu, struct in_addr *pnet_addr, int net_proto ); +LOCAL void cacRingBufferInit(struct ca_buffer *pBuf, unsigned long size); -#else +#else /*__STDC__*/ LOCAL void tcp_recv_msg(); LOCAL void cac_flush_internal(); -LOCAL int cac_send_msg_piiu(); +LOCAL void cac_send_msg_piiu(); LOCAL void notify_ca_repeater(); -LOCAL void recv_msg(); LOCAL void udp_recv_msg(); #ifdef VMS void vms_recv_msg_ast(); -#endif +#endif /*VMS*/ LOCAL int create_net_chan(); +#ifdef JUNKYARD LOCAL void clean_iiu_list(); - #endif +LOCAL void ca_process_tcp(); +LOCAL void ca_process_udp(); +LOCAL void ca_process_input_queue(); +LOCAL void close_ioc(); +LOCAL void cacRingBufferInit(); + +#endif /*__STDC__*/ /* @@ -185,7 +198,6 @@ LOCAL void clean_iiu_list(); * * allocate and initialize an IOC info block for unallocated IOC * - * LOCK should be on while in this routine */ #ifdef __STDC__ int alloc_ioc( @@ -209,6 +221,7 @@ struct ioc_in_use **ppiiu; * quite a bottle neck with increasing connection count * */ + LOCK; for( piiu = (struct ioc_in_use *) iiuList.node.next; piiu; piiu = (struct ioc_in_use *) piiu->node.next){ @@ -221,9 +234,11 @@ struct ioc_in_use **ppiiu; } *ppiiu = piiu; + UNLOCK; return ECA_NORMAL; } } + UNLOCK; status = create_net_chan(ppiiu, pnet_addr, net_proto); return status; @@ -234,7 +249,6 @@ struct ioc_in_use **ppiiu; /* * CREATE_NET_CHANNEL() * - * LOCK should be on while in this routine */ #ifdef __STDC__ LOCAL int create_net_chan( @@ -254,13 +268,22 @@ int net_proto; int sock; int true = TRUE; struct sockaddr_in saddr; - int i; + + LOCK; piiu = (IIU *) calloc(1, sizeof(*piiu)); if(!piiu){ + UNLOCK; return ECA_ALLOCMEM; } + piiu->send_retry_count = SEND_RETRY_COUNT_INIT; + + piiu->active = FALSE; + + piiu->pcas = ca_static; + ellInit(&piiu->chidlist); + piiu->sock_addr.sin_addr = *pnet_addr; piiu->sock_proto = net_proto; @@ -274,19 +297,30 @@ int net_proto; * reset the delay to the next retry or keepalive */ piiu->next_retry = CA_CURRENT_TIME; - piiu->nconn_tries = 0; piiu->retry_delay = CA_RECAST_DELAY; + piiu->nconn_tries = 0; + + /* + * set the minor version ukn until the server + * updates the client + */ + piiu->minor_version_number = CA_UKN_MINOR_VERSION; switch(piiu->sock_proto) { case IPPROTO_TCP: + piiu->recvBytes = tcp_recv_msg; + piiu->sendBytes = cac_send_msg_piiu; + piiu->procInput = ca_process_tcp; + /* allocate a socket */ sock = socket( AF_INET, /* domain */ SOCK_STREAM, /* type */ 0); /* deflt proto */ if(sock == ERROR){ free(piiu); + UNLOCK; return ECA_SOCK; } @@ -308,6 +342,7 @@ int net_proto; if(status<0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return ECA_SOCK; } @@ -329,6 +364,7 @@ int net_proto; if(status<0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return ECA_SOCK; } @@ -366,6 +402,7 @@ int net_proto; if(status<0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return ECA_SOCK; } i = MAX_MSG_SIZE; @@ -381,9 +418,9 @@ int net_proto; if(status<0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return ECA_SOCK; } -#endif /* fetch the TCP send buffer size */ i = sizeof(piiu->tcp_send_buff_size); @@ -399,8 +436,10 @@ int net_proto; if(status<0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return ECA_SOCK; } +#endif /* connect */ status = connect( @@ -414,9 +453,11 @@ int net_proto; SEVCHK(ECA_INTERNAL,NULL); } free(piiu); + UNLOCK; return ECA_CONN; } - piiu->max_msg = MAX_TCP; + cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf)); + cacRingBufferInit(&piiu->send, sizeof(piiu->send.buf)); /* * Set non blocking IO for UNIX @@ -433,25 +474,26 @@ int net_proto; * Save the Host name for efficient access in the * future. */ - { - char *ptmpstr; - - ptmpstr = host_from_addr(&piiu->sock_addr.sin_addr); - strncpy( - piiu->host_name_str, - ptmpstr, - sizeof(piiu->host_name_str)-1); - } + host_from_addr( + &piiu->sock_addr.sin_addr, + piiu->host_name_str, + sizeof(piiu->host_name_str)); break; case IPPROTO_UDP: + + piiu->recvBytes = udp_recv_msg; + piiu->sendBytes = cac_send_msg_piiu; + piiu->procInput = ca_process_udp; + /* allocate a socket */ sock = socket( AF_INET, /* domain */ SOCK_DGRAM, /* type */ 0); /* deflt proto */ if(sock == ERROR){ free (piiu); + UNLOCK; return ECA_SOCK; } @@ -474,6 +516,7 @@ int net_proto; if(status < 0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return ECA_CONN; } @@ -482,7 +525,7 @@ int net_proto; /* * let slib pick lcl addr */ - saddr.sin_addr.s_addr = htonl(INADDR_ANY); + saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(0); status = bind( sock, @@ -493,18 +536,13 @@ int net_proto; ca_signal(ECA_INTERNAL,"bind failed"); } - piiu->max_msg = MAX_UDP - sizeof(piiu->send->stk); + cacRingBufferInit(&piiu->recv, sizeof(piiu->send.buf)); + cacRingBufferInit(&piiu->send, min(MAX_UDP, sizeof(piiu->send.buf))); - /* - * Save the Host name for efficient access in the - * future. - */ - { - strncpy( - piiu->host_name_str, - "<>", - sizeof(piiu->host_name_str)-1); - } + strncpy( + piiu->host_name_str, + "<>", + sizeof(piiu->host_name_str)-1); break; @@ -514,39 +552,10 @@ int net_proto; /* * turn off gcc warnings */ + UNLOCK; return ECA_INTERNAL; } - /* setup cac_send_msg(), recv_msg() buffers */ - if(!piiu->send){ - if(! (piiu->send = (struct buffer *) - malloc(sizeof(struct buffer))) ){ - status = socket_close(sock); - if(status < 0){ - SEVCHK(ECA_INTERNAL,NULL); - } - free(piiu); - return ECA_ALLOCMEM; - } - } - - piiu->send->stk = 0; - - if(!piiu->recv){ - if(! (piiu->recv = (struct buffer *) - malloc(sizeof(struct buffer))) ){ - status = socket_close(sock); - if(status < 0){ - SEVCHK(ECA_INTERNAL,NULL); - } - free(piiu); - return ECA_ALLOCMEM; - } - } - - piiu->send_retry_count = SEND_RETRY_COUNT_INIT; - piiu->recv->stk = 0; - piiu->active = FALSE; if(fd_register_func){ LOCKEVENTS; (*fd_register_func)(fd_register_arg, sock, TRUE); @@ -588,6 +597,8 @@ int net_proto; piiu->conn_up = TRUE; *ppiiu = piiu; + UNLOCK; + return ECA_NORMAL; } @@ -601,8 +612,6 @@ int net_proto; * NOTES: * 1) local communication only (no LAN traffic) * - * LOCK should be on while in this routine - * (MULTINET TCP/IP routines are not reentrant) */ LOCAL void notify_ca_repeater() { @@ -614,6 +623,7 @@ LOCAL void notify_ca_repeater() if(!piiuCast->conn_up) return; + LOCK; /*MULTINET TCP/IP routines are not reentrant*/ status = local_addr(piiuCast->sock_chan, &saddr); if(status == OK){ saddr.sin_port = htons(CA_CLIENT_PORT); @@ -625,204 +635,114 @@ LOCAL void notify_ca_repeater() (struct sockaddr *)&saddr, sizeof saddr); if(status < 0){ - if( MYERRNO == EINTR || - MYERRNO == ENOBUFS || - MYERRNO == EWOULDBLOCK){ - TCPDELAY; - } - else{ + if( MYERRNO != EINTR && + MYERRNO != ENOBUFS && + MYERRNO != EWOULDBLOCK){ ca_printf( "CAC: notify_ca_repeater: send to lcl addr failed\n"); abort(0); } } } + UNLOCK; } - -/* - * CAC_SEND_MSG() - * - * - * LOCK should be on while in this routine - */ -void cac_send_msg() -{ - register struct ioc_in_use *piiu; - int done; - int status; - - for( piiu=(IIU *)iiuList.node.next; - piiu; - piiu=(IIU *)piiu->node.next){ - - piiu->send_retry_count = SEND_RETRY_COUNT_INIT; - } - - if(!ca_static->ca_repeater_contacted) - notify_ca_repeater(); - - send_msg_active++; - - /* - * Dont exit until all connections are flushed - * - */ - while(TRUE){ - /* - * Ensure we do not accumulate extra recv - * messages (for TCP) - * - * frees up push pull deadlock only - * if recv not already in progress - */ -# if defined(UNIX) - if(post_msg_active==0){ - recv_msg_select(¬imeout); - } -# endif - - done = TRUE; - for( piiu=(IIU *)iiuList.node.next; - piiu; - piiu=(IIU *)piiu->node.next){ - - if(!piiu->send->stk || !piiu->conn_up) - continue; - - status = cac_send_msg_piiu(piiu); - if(status<0){ - if(piiu->send_retry_count == 0){ - ca_signal( - ECA_DLCKREST, - piiu->host_name_str); - close_ioc(piiu); - } - else{ - piiu->send_retry_count--; - done = FALSE; - } - } - } - - if(done){ - /* - * always double check that we - * are finished in case somthing was added - * to a send buffer and a recursive - * ca_send_msg() call was refused above - */ - for( piiu=(IIU *)iiuList.node.next; - piiu; - piiu=(IIU *)piiu->node.next){ - - if(piiu->send->stk && piiu->conn_up){ - done = FALSE; - } - } - if(done) - break; - } - - TCPDELAY; - } - - send_msg_active--; -} /* * CAC_SEND_MSG_PIIU() * - * */ #ifdef __STDC__ -LOCAL int cac_send_msg_piiu(struct ioc_in_use *piiu) +LOCAL void cac_send_msg_piiu(struct ioc_in_use *piiu) #else -LOCAL int cac_send_msg_piiu(piiu) +LOCAL void cac_send_msg_piiu(piiu) struct ioc_in_use *piiu; #endif { - unsigned cnt; - void *pmsg; - int status; - - cnt = piiu->send->stk; - pmsg = (void *) piiu->send->buf; - - while(TRUE){ - - status = sendto( - piiu->sock_chan, - pmsg, - cnt, - 0, - (struct sockaddr *)&piiu->sock_addr, - sizeof(piiu->sock_addr)); - - /* - * normal fast exit - */ - if(status == cnt){ - break; - } - else if(status>0){ - if(status>cnt){ - ca_signal( - ECA_INTERNAL, - "more sent than requested ?"); - } - - cnt = cnt-status; - pmsg = (void *) (status+(char *)pmsg); - } - else if(status == 0){ - ca_printf("CAC: sent zero ?\n"); - TCPDELAY; - } - else if(MYERRNO == EWOULDBLOCK || - MYERRNO == ENOBUFS || - MYERRNO == EINTR){ - if(pmsg != piiu->send->buf){ - /* - * realign the message if this - * was a partial send - */ - memcpy( piiu->send->buf, - pmsg, - cnt); - piiu->send->stk = cnt; - } - - return ERROR; - } - else{ - if( MYERRNO != EPIPE && - MYERRNO != ECONNRESET && - MYERRNO != ETIMEDOUT){ - ca_printf( - "CAC: error on socket send() %d\n", - MYERRNO); - } - close_ioc(piiu); - return OK; - } - - - } - - /* reset send stack */ - piiu->send->stk = 0; - piiu->send_needed = FALSE; + unsigned long sendCnt; + int status; /* - * reset the delay to the next keepalive + * check for shutdown in progress */ - if(piiu != piiuCast){ - piiu->next_retry = time(NULL) + CA_RETRY_PERIOD; + if(!piiu->conn_up){ + return; } - return OK; + LOCK; + + sendCnt = cacRingBufferReadSize(&piiu->send, TRUE); + + assert(sendCnt<=piiu->send.max_msg); + + /* + * return if nothing to send + */ + if(sendCnt == 0){ + UNLOCK; + return; + } + + status = sendto( + piiu->sock_chan, + &piiu->send.buf[piiu->send.rdix], + sendCnt, + 0, + (struct sockaddr *)&piiu->sock_addr, + sizeof(piiu->sock_addr)); + + if(status>=0){ + assert(status!=0); + assert(status<=sendCnt); + + /* + * reset the delay to the next keepalive + */ + if(piiu != piiuCast && status){ + piiu->next_retry = time(NULL) + CA_RETRY_PERIOD; + } + + CAC_RING_BUFFER_READ_ADVANCE(&piiu->send, status); + + /* + * forces UDP send buffer to be a + * queue instead of a ring buffer + * (solves ring boundary problems) + */ + if(piiu->sock_proto == IPPROTO_UDP){ + cacRingBufferInit( + &piiu->send, + min(MAX_UDP, sizeof(piiu->send.buf))); + } + + sendCnt = cacRingBufferReadSize(&piiu->send, FALSE); + if(sendCnt==0){ + piiu->send_needed = FALSE; + } + + UNLOCK; + return; + } + + if( MYERRNO == EWOULDBLOCK || + MYERRNO == ENOBUFS || + MYERRNO == EINTR){ + UNLOCK; + return; + } + + if( MYERRNO != EPIPE && + MYERRNO != ECONNRESET && + MYERRNO != ETIMEDOUT){ + ca_printf( + "CAC: error on socket send() %d\n", + MYERRNO); + } + + piiu->conn_up = FALSE; + UNLOCK; + return; } @@ -837,195 +757,215 @@ LOCAL void cac_flush_internal() { register struct ioc_in_use *piiu; - LOCK + LOCK; for( piiu = (IIU *)iiuList.node.next; piiu; piiu = (IIU *)piiu->node.next){ - if(piiu->send->stk==0 || !piiu->send_needed || !piiu->conn_up) + if(!piiu->conn_up){ continue; - + } + if(!piiu->send_needed){ + continue; + } cac_send_msg_piiu(piiu); } - UNLOCK + UNLOCK; } /* - * RECV_MSG_SELECT() + * CA_MUX_IO() * * Asynch notification of incomming messages under UNIX * 1) Wait no longer than timeout * 2) Return early if nothing outstanding + * * */ #if defined(UNIX) || defined(vxWorks) #ifdef __STDC__ -void recv_msg_select(struct timeval *ptimeout) +void ca_mux_io(struct timeval *ptimeout, int flags) #else -void recv_msg_select(ptimeout) +void ca_mux_io(ptimeout, flags) struct timeval *ptimeout; +int flags; #endif { - long status; - register struct ioc_in_use *piiu; - struct timeval timeout; + int count; + int newInput; + struct timeval timeout; - while(TRUE){ + if(!ca_static->ca_repeater_contacted){ + notify_ca_repeater(); + } - LOCK; - for( piiu=(IIU *)iiuList.node.next; - piiu; - piiu=(IIU *)piiu->node.next){ - - if(!piiu->conn_up){ - continue; + timeout = *ptimeout; + do{ + newInput = FALSE; + do{ + count = ca_select_io(&timeout, flags); + if(count>0){ + newInput = TRUE; } - - FD_SET(piiu->sock_chan,&readch); - FD_SET(piiu->sock_chan,&excepch); + timeout.tv_usec = 0; + timeout.tv_sec = 0; } - UNLOCK; + while(count>0); - status = select( - sizeof(fd_set)*NBBY, - &readch, - NULL, - &excepch, - ptimeout); + ca_process_input_queue(); + } + while(newInput); +} +#endif - if(status<=0){ - if(status == 0) - break; - - if(MYERRNO == EINTR){ - ca_printf("CAC: select was interrupted\n"); - TCPDELAY; - continue; - } - else if(MYERRNO == EWOULDBLOCK){ - ca_printf("CAC: blocked at select ?\n"); - break; - } - else{ - char text[255]; - sprintf( - text, - "CAC: unexpected select fail: %d", - MYERRNO); - ca_signal(ECA_INTERNAL,text); - } - } - - /* - * I dont want to lock while traversing - * this list so that we are free to take - * it at a lower level - * - * I know that an item can be added to the - * end of the list while traversing it - * - no lock required here. - * - * I know that an item is only deleted from - * this list in this routine - * - no lock required here. - * - * LOCK is applied when if a block is added - */ - for( piiu=(IIU *)iiuList.node.next; - piiu; - piiu=(IIU *)piiu->node.next){ - - if(!piiu->conn_up){ - continue; - } - - if(FD_ISSET(piiu->sock_chan,&readch) || - FD_ISSET(piiu->sock_chan,&excepch)){ - recv_msg(piiu); - } - } - - /* - * double check to make sure that nothing is left pending - */ - timeout.tv_sec =0; - timeout.tv_usec = 0; - ptimeout = &timeout; - } + +/* + * ca_select_io() + */ +#if defined(UNIX) || defined(vxWorks) +#ifdef __STDC__ +int ca_select_io(struct timeval *ptimeout, int flags) +#else +int ca_select_io(ptimeout, flags) +struct timeval *ptimeout; +int flags; +#endif +{ + long status; + IIU *piiu; + unsigned long minfreespace; + unsigned long freespace; LOCK; - clean_iiu_list(); + piiu=(IIU *)iiuList.node.next; + while(piiu){ + + /* + * clean out dead wood + */ + if(!piiu->conn_up){ + IIU *pnextiiu; + + pnextiiu = (IIU *)piiu->node.next; + close_ioc(piiu); + piiu = pnextiiu; + continue; + } + + /* + * Dont bother receiving if we have insufficient + * space for the maximum UDP message + */ + if(flags&CA_DO_RECVS){ + freespace = cacRingBufferWriteSize(&piiu->recv, TRUE); + if(piiu->sock_proto == IPPROTO_UDP){ + minfreespace = + MAX_UDP+2*sizeof(struct udpmsglog); + } + else{ + minfreespace = 1; + } + + if(freespace>=minfreespace){ + FD_SET(piiu->sock_chan,&readch); + } + } + + if(flags&CA_DO_SENDS){ + if(cacRingBufferReadSize(&piiu->send, FALSE)>0){ + FD_SET(piiu->sock_chan,&writech); + } + } + + piiu=(IIU *)piiu->node.next; + } + UNLOCK; + + status = select( + sizeof(fd_set)*NBBY, + &readch, + &writech, + NULL, + ptimeout); + + if(status<0){ + if(MYERRNO == EINTR){ + } + else if(MYERRNO == EWOULDBLOCK){ + ca_printf("CAC: blocked at select ?\n"); + } + else{ + char text[255]; + sprintf( + text, + "CAC: unexpected select fail: %d", + MYERRNO); + SEVCHK(ECA_INTERNAL,text); + } + } + + LOCK; + if(status>0){ + for( piiu=(IIU *)iiuList.node.next; + piiu; + piiu=(IIU *)piiu->node.next){ + + if(!piiu->conn_up){ + continue; + } + + if(flags&CA_DO_SENDS && + FD_ISSET(piiu->sock_chan,&writech)){ + (*piiu->sendBytes)(piiu); + } + + if(flags&CA_DO_RECVS && + FD_ISSET(piiu->sock_chan,&readch)){ + (*piiu->recvBytes)(piiu); + } + + FD_CLR(piiu->sock_chan,&readch); + FD_CLR(piiu->sock_chan,&writech); + } + } + UNLOCK; + + return status; +} +#endif + + +/* + * ca_process_input_queue() + */ +LOCAL void ca_process_input_queue() +{ + struct ioc_in_use *piiu; + + /* + * dont allow recursion + */ + if(post_msg_active){ + return; + } + + LOCK; + for( piiu=(IIU *)iiuList.node.next; + piiu; + piiu=(IIU *)piiu->node.next){ + + if(!piiu->conn_up){ + continue; + } + + (*piiu->procInput)(piiu); + } UNLOCK; cac_flush_internal(); } -#endif - -/* - * clean_iiu_list() - */ -LOCAL void clean_iiu_list() -{ - IIU *piiu; - - piiu=(IIU *)iiuList.node.next; - while(piiu){ - IIU *pnext; - - /* - * iiu block may be deleted here - * so I save the pointer to the next - * block - */ - pnext=(IIU *)piiu->node.next; - if(!piiu->conn_up){ - ellDelete(&iiuList, &piiu->node); - free(piiu); - } - piiu=pnext; - } -} - - -/* - * RECV_MSG() - * - * - */ -#ifdef __STDC__ -LOCAL void recv_msg(struct ioc_in_use *piiu) -#else -LOCAL void recv_msg(piiu) -struct ioc_in_use *piiu; -#endif -{ - if(!piiu->conn_up){ - return; - } - - piiu->active = TRUE; - - switch(piiu->sock_proto){ - case IPPROTO_TCP: - - tcp_recv_msg(piiu); - flow_control(piiu); - - break; - - case IPPROTO_UDP: - udp_recv_msg(piiu); - break; - - default: - ca_printf("CAC: cac_send_msg: ukn protocol\n"); - abort(0); - } - - piiu->active = FALSE; -} /* @@ -1039,30 +979,34 @@ LOCAL void tcp_recv_msg(piiu) struct ioc_in_use *piiu; #endif { - long byte_cnt; - int status; - struct buffer *rcvb = piiu->recv; - int sock = piiu->sock_chan; + unsigned long writeSpace; + int status; - if(!ca_static->ca_repeater_contacted){ - LOCK; - notify_ca_repeater(); - UNLOCK; + if(!piiu->conn_up){ + return; } - status = recv( sock, - &rcvb->buf[rcvb->stk], - sizeof(rcvb->buf) - rcvb->stk, + + LOCK; + + writeSpace = cacRingBufferWriteSize(&piiu->recv, TRUE); + if(writeSpace == 0){ + UNLOCK; + return; + } + + status = recv( piiu->sock_chan, + &piiu->recv.buf[piiu->recv.wtix], + writeSpace, 0); if(status == 0){ - LOCK; - close_ioc(piiu); + piiu->conn_up = FALSE; UNLOCK; return; } else if(status <0){ /* try again on status of -1 and no luck this time */ if(MYERRNO == EWOULDBLOCK || MYERRNO == EINTR){ - TCPDELAY; + UNLOCK; return; } @@ -1072,53 +1016,21 @@ struct ioc_in_use *piiu; ca_printf( "CAC: unexpected recv error (errno=%d)\n", MYERRNO); } - LOCK; - close_ioc(piiu); + piiu->conn_up = FALSE; UNLOCK; return; } - byte_cnt = (long) status; - if(byte_cnt>MAX_MSG_SIZE){ + if(status>MAX_MSG_SIZE){ ca_printf( "CAC: recv_msg(): message overflow %l\n", - byte_cnt-MAX_MSG_SIZE); - LOCK; - close_ioc(piiu); + status-MAX_MSG_SIZE); + piiu->conn_up = FALSE; UNLOCK; return; } - piiu->send_retry_count = SEND_RETRY_COUNT_INIT; - - rcvb->stk += byte_cnt; - - /* post message to the user */ - byte_cnt = rcvb->stk; - status = post_msg( - (struct extmsg *)rcvb->buf, - &byte_cnt, - &piiu->sock_addr.sin_addr, - piiu); - if(status != OK){ - LOCK; - close_ioc(piiu); - UNLOCK; - return; - } - if(byte_cnt>0){ - /* - * realign partial message - */ - memcpy( rcvb->buf, - rcvb->buf + rcvb->stk - byte_cnt, - byte_cnt); -#ifdef DEBUG - ca_printf( "CAC: realigned message of %d bytes\n", - byte_cnt); -#endif - } - rcvb->stk = byte_cnt; + CAC_RING_BUFFER_WRITE_ADVANCE(&piiu->recv, status); /* * reset the delay to the next keepalive @@ -1127,6 +1039,62 @@ struct ioc_in_use *piiu; piiu->next_retry = time(NULL) + CA_RETRY_PERIOD; } + UNLOCK; + return; +} + + +/* + * ca_process_tcp() + * + */ +#ifdef __STDC__ +LOCAL void ca_process_tcp(struct ioc_in_use *piiu) +#else +LOCAL void ca_process_tcp(piiu) +struct ioc_in_use *piiu; +#endif +{ + int status; + long bytesToProcess; + + /* + * dont allow recursion + */ + if(post_msg_active){ + return; + } + + post_msg_active++; + + LOCK; + while(TRUE){ + bytesToProcess = cacRingBufferReadSize(&piiu->recv, TRUE); + if(bytesToProcess == 0){ + break; + } + + /* post message to the user */ + status = post_msg( + piiu, + &piiu->sock_addr.sin_addr, + &piiu->recv.buf[piiu->recv.rdix], + bytesToProcess); + if(status != OK){ + piiu->conn_up = FALSE; + post_msg_active--; + return; + } + CAC_RING_BUFFER_READ_ADVANCE( + &piiu->recv, + bytesToProcess); + } + UNLOCK; + + post_msg_active--; + + flow_control(piiu); + return; } @@ -1144,92 +1112,158 @@ struct ioc_in_use *piiu; #endif { int status; - struct buffer *rcvb = piiu->recv; - int sock = piiu->sock_chan; int reply_size; - unsigned nchars; - struct msglog{ - long nbytes; - struct sockaddr_in addr; - }; - struct msglog *pmsglog; + struct udpmsglog *pmsglog; + unsigned long bytesAvailable; + if(!piiu->conn_up){ + return; + } + LOCK; - rcvb->stk =0; - while(TRUE){ + bytesAvailable = cacRingBufferWriteSize(&piiu->recv, TRUE); + assert(bytesAvailable >= MAX_UDP+2*sizeof(*pmsglog)); + pmsglog = (struct udpmsglog *) &piiu->recv.buf[piiu->recv.wtix]; - pmsglog = (struct msglog *) &rcvb->buf[rcvb->stk]; - rcvb->stk += sizeof(*pmsglog); - - reply_size = sizeof(pmsglog->addr); - status = recvfrom( - sock, - &rcvb->buf[rcvb->stk], - MAX_UDP, - 0, - (struct sockaddr *)&pmsglog->addr, - &reply_size); - if(status < 0){ - /* - * op would block which is ok to ignore till ready - * later - */ - if(MYERRNO == EWOULDBLOCK || MYERRNO == EINTR) - break; - ca_signal(ECA_INTERNAL,"unexpected udp recv error"); - } - else if(status == 0){ - break; + reply_size = sizeof(pmsglog->addr); + status = recvfrom( + piiu->sock_chan, + (char *)(pmsglog+1), + MAX_UDP, + 0, + (struct sockaddr *)&pmsglog->addr, + &reply_size); + if(status < 0){ + /* + * op would block which is ok to ignore till ready + * later + */ + if(MYERRNO == EWOULDBLOCK || MYERRNO == EINTR){ + UNLOCK; + return; } + ca_printf("Unexpected UDP failure %d\n", MYERRNO); + piiu->conn_up = FALSE; + } + else if(status > 0){ + unsigned long bytesActual; /* - * log the msg size - */ - rcvb->stk += status; + * log the msg size + * and advance the ring index + */ pmsglog->nbytes = (long) status; -#ifdef DEBUG - ca_printf("CAC: recieved a udp reply of %d bytes\n",byte_cnt); + pmsglog->valid = TRUE; + bytesActual = status + sizeof(*pmsglog); + CAC_RING_BUFFER_WRITE_ADVANCE(&piiu->recv, bytesActual); + /* + * if there isnt enough room at the end advance + * to the beginning of the ring + */ + bytesAvailable = cacRingBufferWriteSize(&piiu->recv, TRUE); + if( bytesAvailable < MAX_UDP+2*sizeof(*pmsglog) ){ + assert(bytesAvailable>=sizeof(*pmsglog)); + pmsglog = (struct udpmsglog *) + &piiu->recv.buf[piiu->recv.wtix]; + pmsglog->valid = FALSE; + pmsglog->nbytes = bytesAvailable - sizeof(*pmsglog); + CAC_RING_BUFFER_WRITE_ADVANCE( + &piiu->recv, bytesAvailable); + } +# ifdef DEBUG + ca_printf( + "%s: udp reply of %d bytes\n", + __FILE__, + byte_cnt); +# endif + } + + UNLOCK; + + return; +} + + + +/* + * CA_PROCESS_UDP() + * + */ +#ifdef __STDC__ +LOCAL void ca_process_udp(struct ioc_in_use *piiu) +#else +LOCAL void ca_process_udp(piiu) +struct ioc_in_use *piiu; #endif +{ + int status; + struct udpmsglog *pmsglog; + char *pBuf; + unsigned long bytesAvailable; - if(rcvb->stk + MAX_UDP + sizeof(*pmsglog) > MAX_MSG_SIZE) - break; + /* + * dont allow recursion + */ + if(post_msg_active){ + return; + } - /* - * More comming ? - */ - status = socket_ioctl( sock, - FIONREAD, - (int) &nchars); - if(status<0) - ca_signal(ECA_INTERNAL,"unexpected udp ioctl err\n"); - if(nchars==0) + post_msg_active++; + + LOCK; + while(TRUE){ + + bytesAvailable = cacRingBufferReadSize(&piiu->recv, TRUE); + if(bytesAvailable == 0){ break; - } - - pmsglog = (struct msglog *) rcvb->buf; - while(pmsglog < (struct msglog *)&rcvb->buf[rcvb->stk]){ - long msgcount; - - /* post message to the user */ - msgcount = pmsglog->nbytes; - status = post_msg( - (struct extmsg *)(pmsglog+1), - &msgcount, - &pmsglog->addr.sin_addr, - piiu); - if(status != OK || msgcount != 0){ - ca_printf("CAC: bad UDP msg from port=%d addr=%x align=%d\n", - pmsglog->addr.sin_port, - pmsglog->addr.sin_addr.s_addr, - msgcount); } - pmsglog = (struct msglog *) - (pmsglog->nbytes + (char *) (pmsglog+1)); + assert(bytesAvailable>=sizeof(*pmsglog)); + + pBuf = &piiu->recv.buf[piiu->recv.rdix]; + while(pBuf<&piiu->recv.buf[piiu->recv.rdix]+bytesAvailable){ + pmsglog = (struct udpmsglog *) pBuf; + + /* post message to the user */ + if(pmsglog->valid){ + status = post_msg( + piiu, + &pmsglog->addr.sin_addr, + (char *)(pmsglog+1), + pmsglog->nbytes); + if(status != OK || piiu->curMsgBytes){ + ca_printf( + "%s: bad UDP msg from port=%d addr=%x\n", + __FILE__, + pmsglog->addr.sin_port, + pmsglog->addr.sin_addr.s_addr); + /* + * resync the ring buffer + * (discard existing messages) + */ + cacRingBufferInit( + &piiu->recv, + sizeof(piiu->recv.buf)); + piiu->curMsgBytes = 0; + piiu->curDataBytes = 0; + post_msg_active--; + UNLOCK; + return; + } + } + pBuf += sizeof(*pmsglog)+pmsglog->nbytes; + } + CAC_RING_BUFFER_READ_ADVANCE( + &piiu->recv, + bytesAvailable); } - + + UNLOCK; + + post_msg_active--; + return; } @@ -1243,10 +1277,10 @@ struct ioc_in_use *piiu; */ #ifdef __STDC__ void cac_recv_task(int tid) -#else +#else /*__STDC__*/ void cac_recv_task(tid) int tid; -#endif +#endif /*__STDC__*/ { struct timeval timeout; int status; @@ -1257,16 +1291,16 @@ int tid; SEVCHK(status, NULL); /* - * detects connection loss and self exits - * in close_ioc() + * once started, does not exit until + * ca_task_exit() is called. */ while(TRUE){ timeout.tv_usec = 0; timeout.tv_sec = 20; - recv_msg_select(&timeout); + ca_mux_io(&timeout, CA_DO_RECVS); } } -#endif +#endif /*vxWorks*/ /* @@ -1278,17 +1312,17 @@ int tid; #ifdef VMS #ifdef __STDC__ LOCAL void vms_recv_msg_ast(struct ioc_in_use *piiu) -#else +#else /*__STDC__*/ LOCAL void vms_recv_msg_ast(piiu) struct ioc_in_use *piiu; -#endif +#endif /*__STDC__*/ { short io_status; io_status = piiu->iosb.status; if(io_status != SS$_NORMAL){ - close_ioc(piiu); + close_ioc(piiu); if(io_status != SS$_CANCEL) lib$signal(io_status); return; @@ -1297,9 +1331,14 @@ struct ioc_in_use *piiu; if(!ca_static->ca_repeater_contacted) notify_ca_repeater(); - recv_msg(piiu); - clean_iiu_list(); - cac_flush_internal(); + if(piiu->conn_up){ + (*piiu->recvBytes)(piiu); + ca_process_input_queue(); + } + else{ + close_ioc(piiu); + return; + } /* * request to be informed of future IO @@ -1321,7 +1360,7 @@ struct ioc_in_use *piiu; lib$signal(io_status); return; } -#endif +#endif /*VMS*/ /* @@ -1331,51 +1370,39 @@ struct ioc_in_use *piiu; * set an iiu in the disconnected state * * - * NOTES: - * Lock must be applied while in this routine */ #ifdef __STDC__ -void close_ioc(struct ioc_in_use *piiu) -#else -void close_ioc(piiu) +LOCAL void close_ioc(struct ioc_in_use *piiu) +#else /*__STDC__*/ +LOCAL void close_ioc(piiu) struct ioc_in_use *piiu; -#endif +#endif /*__STDC__*/ { chid chix; struct connection_handler_args args; int status; - if(!piiu->conn_up){ + + /* + * dont close twice + */ + if(piiu->sock_chan == -1){ return; } - piiu->conn_up = FALSE; + + LOCK; + + ellDelete(&iiuList, &piiu->node); + + /* + * attempt to clear out messages in recv queue + */ + (*piiu->procInput)(piiu); if(piiu == piiuCast){ piiuCast = NULL; } - /* - * reset send stack- discard pending ops when the conn broke (assume - * use as UDP buffer during disconn) - */ - piiu->send->stk = 0; - piiu->recv->stk = 0; - piiu->max_msg = MAX_UDP; - piiu->active = FALSE; - - /* - * reset the delay to the next retry - */ - piiu->next_retry = CA_CURRENT_TIME; - piiu->nconn_tries = 0; - piiu->retry_delay = CA_RECAST_DELAY; - -# if defined(UNIX) || defined(vxWorks) - /* clear unused select bit */ - FD_CLR(piiu->sock_chan, &readch); - FD_CLR(piiu->sock_chan, &excepch); -# endif - /* * Mark all of their channels disconnected * prior to calling handlers incase the @@ -1391,11 +1418,6 @@ struct ioc_in_use *piiu; chix->id.sid = ~0L; } - if(piiu->chidlist.count){ - ca_signal( - ECA_DISCONN, - piiu->host_name_str); - } /* * remove IOC from the hash table @@ -1438,10 +1460,17 @@ struct ioc_in_use *piiu; /* * move all channels to the broadcast IIU + * + * if we loose the broadcast IIU its a severe error */ if(piiuCast){ ellConcat(&piiuCast->chidlist, &piiu->chidlist); } + else{ + assert(0); + } + + assert(piiu->chidlist.count==0); if(fd_register_func){ LOCKEVENTS; @@ -1450,14 +1479,21 @@ struct ioc_in_use *piiu; } status = socket_close(piiu->sock_chan); - if(status < 0){ - SEVCHK(ECA_INTERNAL,NULL); + assert(status == 0); + + /* + * free message body cache + */ + if(piiu->pCurData){ + free(piiu->pCurData); + piiu->pCurData = NULL; + piiu->curDataMax = 0; } + piiu->sock_chan = -1; - if(!piiuCast){ - ca_printf("Unable to broadcast- channels will not reconnect\n"); - } + free(piiu); + UNLOCK; } @@ -1465,7 +1501,7 @@ struct ioc_in_use *piiu; /* * REPEATER_INSTALLED() * - * Test for the repeater allready installed + * Test for the repeater already installed * * NOTE: potential race condition here can result * in two copies of the repeater being spawned @@ -1495,14 +1531,34 @@ int repeater_installed() int installed = FALSE; + LOCK; + /* allocate a socket */ sock = socket( AF_INET, /* domain */ SOCK_DGRAM, /* type */ 0); /* deflt proto */ if(sock == ERROR){ - abort(0); + UNLOCK; + return 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); + status = bind( sock, + (struct sockaddr *) &bd, + sizeof bd); + if(status<0){ + if(MYERRNO == EADDRINUSE){ + installed = TRUE; + } + } + + /* + * turn on reuse only after the test so that + * this works on UNIX kernels that support multicast + */ status = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, @@ -1512,24 +1568,243 @@ int repeater_installed() ca_printf( "CAC: set socket option reuseaddr failed\n"); } - memset((char *)&bd,0,sizeof bd); - bd.sin_family = AF_INET; - bd.sin_addr.s_addr = htonl(INADDR_ANY); - bd.sin_port = htons(CA_CLIENT_PORT); - status = bind( sock, - (struct sockaddr *) &bd, - sizeof bd); - if(status<0) - if(MYERRNO == EADDRINUSE) - installed = TRUE; - else - abort(0); - status = socket_close(sock); if(status<0){ SEVCHK(ECA_INTERNAL,NULL); } + UNLOCK; return installed; } + + + +/* + * cacRingBufferRead() + * + * returns the number of bytes read which may be less than + * the number requested. + */ +#ifdef __STDC__ +unsigned long cacRingBufferRead( +struct ca_buffer *pRing, +void *pBuf, +unsigned long nBytes) +#else /*__STDC__*/ +unsigned long cacRingBufferRead(pRing, pBuf, nBytes) +struct ca_buffer *pRing; +void *pBuf; +unsigned long nBytes; +#endif /*__STDC__*/ +{ + unsigned long potentialBytes; + unsigned long actualBytes; + char *pCharBuf; + + actualBytes = 0; + pCharBuf = pBuf; + while(TRUE){ + potentialBytes = cacRingBufferReadSize(pRing, TRUE); + if(potentialBytes == 0){ + return actualBytes; + } + potentialBytes = min(potentialBytes, nBytes-actualBytes); + memcpy(pCharBuf, &pRing->buf[pRing->rdix], potentialBytes); + CAC_RING_BUFFER_READ_ADVANCE(pRing, potentialBytes); + pCharBuf += potentialBytes; + actualBytes += potentialBytes; + if(nBytes <= actualBytes){ + return actualBytes; + } + } +} + + +/* + * cacRingBufferWrite() + * + * returns the number of bytes written which may be less than + * the number requested. + */ +#ifdef __STDC__ +unsigned long cacRingBufferWrite( +struct ca_buffer *pRing, +void *pBuf, +unsigned long nBytes) +#else /*__STDC__*/ +unsigned long cacRingBufferWrite(pRing,pBuf,nBytes); +struct ca_buffer *pRing; +void *pBuf; +unsigned long nBytes; +#endif /*__STDC__*/ +{ + unsigned long potentialBytes; + unsigned long actualBytes; + char *pCharBuf; + + actualBytes = 0; + pCharBuf = pBuf; + while(TRUE){ + potentialBytes = cacRingBufferWriteSize(pRing, TRUE); + if(potentialBytes == 0){ + return actualBytes; + } + potentialBytes = min(potentialBytes, nBytes-actualBytes); + memcpy(pRing->buf+pRing->wtix, pCharBuf, potentialBytes); + CAC_RING_BUFFER_WRITE_ADVANCE(pRing, potentialBytes); + pCharBuf += potentialBytes; + actualBytes += potentialBytes; + if(nBytes <= actualBytes){ + return actualBytes; + } + } +} + + + +/* + * cacRingBufferInit() + * + */ +#ifdef __STDC__ +LOCAL void cacRingBufferInit(struct ca_buffer *pBuf, unsigned long size) +#else /*__STDC__*/ +LOCAL void cacRingBufferInit(pBuf, unsigned long size) +struct ca_buffer *pBuf; +#endif /*__STDC__*/ +{ + assert(size<=sizeof(pBuf->buf)); + pBuf->max_msg = size; + pBuf->rdix = 0; + pBuf->wtix = 0; + pBuf->readLast = TRUE; +} + + +/* + * cacRingBufferReadSize() + * + * returns N bytes available + * (not nec contiguous) + */ +#ifdef __STDC__ +unsigned long cacRingBufferReadSize(struct ca_buffer *pBuf, int contiguous) +#else /*__STDC__*/ +unsigned long cacRingBufferReadSize(pBuf, contiguous) +struct ca_buffer *pBuf; +int contiguous; +#endif /*__STDC__*/ +{ + unsigned long count; + + if(pBuf->wtix < pBuf->rdix){ + count = pBuf->max_msg - pBuf->rdix; + if(!contiguous){ + count += pBuf->wtix; + } + } + else if(pBuf->wtix > pBuf->rdix){ + count = pBuf->wtix - pBuf->rdix; + } + else if(pBuf->readLast){ + count = 0; + } + else{ + if(contiguous){ + count = pBuf->max_msg - pBuf->rdix; + } + else{ + count = pBuf->max_msg; + } + } + +#if 0 + printf("%d bytes available for reading \n", count); +#endif + + return count; +} + + +/* + * cacRingBufferWriteSize() + * + * returns N bytes available + * (not nec contiguous) + */ +#ifdef __STDC__ +unsigned long cacRingBufferWriteSize(struct ca_buffer *pBuf, int contiguous) +#else /*__STDC__*/ +unsigned long cacRingBufferWriteSize(pBuf, contiguous) +struct ca_buffer *pBuf; +int contiguous; +#endif /*__STDC__*/ +{ + unsigned long count; + + if(pBuf->wtix < pBuf->rdix){ + count = pBuf->rdix - pBuf->wtix; + } + else if(pBuf->wtix > pBuf->rdix){ + count = pBuf->max_msg - pBuf->wtix; + if(!contiguous){ + count += pBuf->rdix; + } + } + else if(pBuf->readLast){ + if(contiguous){ + count = pBuf->max_msg - pBuf->wtix; + } + else{ + count = pBuf->max_msg; + } + } + else{ + count = 0; + } + +#if 0 + printf("%d bytes available for writing\n", count); +#endif + return count; +} + + + +/* + * localLocationName() + * + * o Indicates failure by setting ptr to nill + * + * o Calls non posix gethostbyname() so that we get DNS style names + * (gethostbyname() should be available will al BSD sock libs) + * + * vxWorks user will need to configure a DNS format name for the + * host name if they wish to be cnsistent UNIX and VMS hosts. + * + */ +char *localLocationName() +{ + int size; + int status; + char pName[MAXHOSTNAMELEN]; + char *pTmp; + + status = gethostname(pName, sizeof(pName)); + if(status){ + return NULL; + } + + size = strlen(pName)+1; + pTmp = malloc(size); + if(!pTmp){ + return pTmp; + } + + strncpy(pTmp, pName, size-1); + pTmp[size-1] = '\0'; + + return pTmp; +} + diff --git a/src/ca/iocinf.h b/src/ca/iocinf.h index 177329182..173fb7d18 100644 --- a/src/ca/iocinf.h +++ b/src/ca/iocinf.h @@ -26,7 +26,8 @@ /* .15 112092 joh added AST lck count var for VMS */ /* .16 120992 joh switched to dll list routines */ /* .17 121892 joh added TCP send buf size var */ -/* .17 122192 joh added outstanding ack var */ +/* .18 122192 joh added outstanding ack var */ +/* .19 012094 joh added minor version (for each server) */ /* */ /*_begin */ /************************************************************************/ @@ -74,6 +75,11 @@ static char *iocinfhSccsId = "$Id$"; # endif #endif +#include +#include + +#include +#include #include #include #include @@ -82,6 +88,20 @@ static char *iocinfhSccsId = "$Id$"; #define min(A,B) ((A)>(B)?(B):(A)) #endif +/* + * catch when they use really large strings + */ +#define STRING_LIMIT 512 + +#define INITCHK \ +if(!ca_static){ \ + int s; \ + s = ca_task_initialize(); \ + if(s != ECA_NORMAL){ \ + return s; \ + } \ +} + /* throw out requests prior to last ECA_TIMEOUT from ca_pend */ #define VALID_MSG(PIIU) (piiu->read_seq == piiu->cur_read_seq) @@ -92,25 +112,21 @@ static char *iocinfhSccsId = "$Id$"; #define SETPENDRECV {pndrecvcnt++;} #define CLRPENDRECV(LOCK) {if(--pndrecvcnt<1){cac_io_done(LOCK); POST_IO_EV;}} -/************************************************************************/ -/* Structures */ -/************************************************************************/ -/* stk must be above and contiguous with buf ! */ -struct buffer{ - char buf[MAX_MSG_SIZE]; /* from iocmsg.h */ - unsigned long stk; + +struct udpmsglog{ + long nbytes; + int valid; + struct sockaddr_in addr; }; - -/* indexs into the ioc in use table */ -#if 0 -#define INVALID_IIU (MAXIIU+1) -#define LOCAL_IIU (MAXIIU+100) -#define BROADCAST_IIU 0 -#endif +/* + * for use with ca_mux_io() + */ +#define CA_DO_SENDS 1 +#define CA_DO_RECVS 2 struct pending_io_event{ - ELLNODE node; + ELLNODE node; void (*io_done_sub)(); void *io_done_arg; }; @@ -135,9 +151,23 @@ typedef struct beaconHashEntry{ int averagePeriod; }bhe; +#ifdef vxWorks +typedef struct caclient_put_notify{ + ELLNODE node; + PUTNOTIFY dbPutNotify; + unsigned long valueSize; /* size of block pointed to by dbPutNotify */ + void (*caUserCallback)(struct event_handler_args); + void *caUserArg; + struct ca_static *pcas; + int busy; +}CACLIENTPUTNOTIFY; +#endif /*vxWorks*/ #define MAX_CONTIGUOUS_MSG_COUNT 2 +/* + * ! lock needs to be applied when an id is allocated ! + */ #define CLIENT_ID_WIDTH 20 /* bits (1 million before rollover) */ #define CLIENT_ID_COUNT (1<ca_nxtiiu) #define free_event_list (ca_static->ca_free_event_list) #define pend_read_list (ca_static->ca_pend_read_list) +#define pend_write_list (ca_static->ca_pend_write_list) #define fd_register_func\ (ca_static->ca_fd_register_func) #define fd_register_arg (ca_static->ca_fd_register_arg) @@ -168,7 +199,6 @@ typedef struct beaconHashEntry{ #if defined(UNIX) || defined(vxWorks) # define readch (ca_static->ca_readch) # define writech (ca_static->ca_writech) -# define excepch (ca_static->ca_excepch) #endif #if defined(UNIX) @@ -201,23 +231,68 @@ typedef struct task_var_list{ int tid; }TVIU; + +/* + * Ring buffering for both sends and recvs + */ +struct ca_buffer{ + char buf[MAX_MSG_SIZE]; /* from iocmsg.h */ + unsigned long max_msg; + unsigned long rdix; + unsigned long wtix; + int readLast; +}; + +#define CAC_RING_BUFFER_INIT(PRBUF, SIZE) \ + assert((SIZE)>sizeof((PRBUF)->buf)); \ + (PRBUF)->max_msg = (SIZE); \ + (PRBUF)->rdix = 0; \ + (PRBUF)->wtix = 0; \ + (PRBUF)->readLast = TRUE; + +#define CAC_RING_BUFFER_READ_ADVANCE(PRBUF, DELTA) \ +( (PRBUF)->readLast = TRUE, \ + ((PRBUF)->rdix += (DELTA)) >= (PRBUF)->max_msg ? \ + (PRBUF)->rdix = 0 : \ + (PRBUF)->rdix \ +) + +#define CAC_RING_BUFFER_WRITE_ADVANCE(PRBUF, DELTA) \ +( (PRBUF)->readLast = FALSE, \ + ((PRBUF)->wtix += (DELTA)) >= (PRBUF)->max_msg ? \ + (PRBUF)->wtix = 0 : \ + (PRBUF)->wtix \ +) + /* * One per IOC */ typedef struct ioc_in_use{ ELLNODE node; - unsigned outstanding_ack_count; - unsigned bytes_pushing_an_ack; + struct ca_static *pcas; + unsigned minor_version_number; unsigned contiguous_msg_count; unsigned client_busy; char active; int sock_proto; struct sockaddr_in sock_addr; int sock_chan; - int max_msg; - int tcp_send_buff_size; - struct buffer *send; - struct buffer *recv; + struct ca_buffer send; + struct ca_buffer recv; + struct extmsg curMsg; + unsigned curMsgBytes; + void *pCurData; + unsigned long curDataMax; + unsigned long curDataBytes; +#ifdef __STDC__ + void (*sendBytes)(struct ioc_in_use *); + void (*recvBytes)(struct ioc_in_use *); + void (*procInput)(struct ioc_in_use *); +#else /*__STDC__*/ + void (*sendBytes)(); + void (*recvBytes)(); + void (*procInput)(); +#endif /*__STDC__*/ unsigned read_seq; unsigned cur_read_seq; ELLLIST chidlist; /* chans on this connection */ @@ -228,26 +303,35 @@ typedef struct ioc_in_use{ unsigned send_retry_count; ca_time next_retry; ca_time retry_delay; -#if defined(VMS) /* for qio ASTs */ + +#ifdef VMS /* for qio ASTs */ + unsigned long putConvertBufSize; + void *pPutConvertBuf; struct sockaddr_in recvfrom; struct iosb iosb; -#else -#if defined(UNIX) -#else -#if defined(vxWorks) -#else - DONT_COMPILE -#endif -#endif -#endif +#endif /*VMS*/ + +#ifdef UNIX +#endif /*UNIX*/ + +#ifdef vxWorks +#endif /*vxWorks*/ + }IIU; struct ca_static{ IIU *ca_piiuCast; ELLLIST ca_iiuList; - long ca_pndrecvcnt; ELLLIST ca_ioeventlist; + ELLLIST ca_free_event_list; + ELLLIST ca_pend_read_list; + ELLLIST ca_pend_write_list; + ELLLIST activeCASG; + ELLLIST freeCASG; + ELLLIST activeCASGOP; + ELLLIST freeCASGOP; + long ca_pndrecvcnt; void (*ca_exception_func)(); void *ca_exception_arg; void (*ca_connection_func)(); @@ -256,18 +340,18 @@ struct ca_static{ void *ca_fd_register_arg; short ca_exit_in_progress; unsigned short ca_post_msg_active; - ELLLIST ca_free_event_list; - ELLLIST ca_pend_read_list; short ca_repeater_contacted; unsigned short ca_send_msg_active; struct in_addr ca_castaddr; - char ca_sprintf_buf[128]; + char ca_sprintf_buf[256]; BUCKET *ca_pBucket; unsigned long ca_nextBucketId; bhe *ca_beaconHash[BHT_INET_ADDR_MASK+1]; + char *ca_pUserName; + char *ca_pLocationName; #if defined(UNIX) || defined(vxWorks) fd_set ca_readch; - fd_set ca_excepch; + fd_set ca_writech; #endif #if defined(VMS) int ca_io_done_flag; @@ -276,13 +360,16 @@ struct ca_static{ #endif #if defined(vxWorks) SEM_ID ca_io_done_sem; + SEM_ID ca_blockSem; void *ca_evuser; - FAST_LOCK ca_client_lock; - FAST_LOCK ca_event_lock; /* dont allow events to preempt */ + SEM_ID ca_client_lock; + SEM_ID ca_event_lock; /* dont allow events to preempt */ + SEM_ID ca_putNotifyLock; int ca_tid; ELLLIST ca_local_chidlist; ELLLIST ca_dbfree_ev_list; ELLLIST ca_lcl_buff_list; + ELLLIST ca_putNotifyQue; int ca_event_tid; unsigned ca_local_ticks; int recv_tid; @@ -318,21 +405,16 @@ struct ca_static *ca_static; #ifdef __STDC__ void cac_send_msg(); -void recv_msg_select(struct timeval *ptimeout); -void close_ioc(struct ioc_in_use *piiu); +void ca_mux_io(struct timeval *ptimeout, int flags); int repeater_installed(); void build_msg(chid chix, int reply_type); -void ca_request_event(evid monix); -int alloc_ioc( -struct in_addr *pnet_addr, -int net_proto, -struct ioc_in_use **ppiiu -); +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 issue_claim_channel(struct ioc_in_use *piiu, chid pchan); -void ca_default_exception_handler(struct exception_handler_args args); +void issue_identify_client(struct ioc_in_use *piiu); +void issue_identify_client_location(struct ioc_in_use *piiu); int ca_defunct(void); int ca_printf(char *pformat, ...); void manage_conn(int silent); @@ -340,21 +422,47 @@ void mark_server_available(struct in_addr *pnet_addr); void flow_control(struct ioc_in_use *piiu); int broadcast_addr(struct in_addr *pcastaddr); int local_addr(int s, struct sockaddr_in *plcladdr); -char *host_from_addr(struct in_addr *pnet_addr); int ca_repeater_task(); void cac_recv_task(int tid); -int post_msg( -struct extmsg *hdrptr, -long *pbufcnt, -struct in_addr *pnet_addr, -struct ioc_in_use *piiu -); void cac_io_done(int lock); +void ca_sg_init(void); +void ca_sg_shutdown(struct ca_static *ca_temp); +int ca_select_io(struct timeval *ptimeout, int flags); -#else +void host_from_addr( + struct in_addr *pnet_addr, + char *pBuf, + unsigned size +); +int post_msg( + struct ioc_in_use *piiu, + struct in_addr *pnet_addr, + char *pInBuf, + unsigned long blockSize +); +int alloc_ioc( + struct in_addr *pnet_addr, + int net_proto, + struct ioc_in_use **ppiiu +); +unsigned long cacRingBufferWrite( + struct ca_buffer *pRing, + void *pBuf, + unsigned long nBytes); +unsigned long cacRingBufferRead( + struct ca_buffer *pRing, + void *pBuf, + unsigned long nBytes); + +unsigned long cacRingBufferWriteSize(struct ca_buffer *pBuf, int contiguous); +unsigned long cacRingBufferReadSize(struct ca_buffer *pBuf, int contiguous); + +char *localUserName(); +char *localLocationName(); + +#else /*__STDC__*/ int ca_defunct(); -void ca_default_exception_handler(); int repeater_installed(); void cac_send_msg(); void build_msg(); @@ -367,17 +475,35 @@ void ca_ready_message(); void flow_control(); char *host_from_addr(); int ca_repeater_task(); -void close_ioc(); -void recv_msg_select(); void mark_server_available(); void issue_claim_channel(); -void ca_request_event(); +int ca_request_event(); void cac_io_done(); int post_msg(); int alloc_ioc(); int ca_printf(); void cac_recv_task(); +void ca_sg_init(); +void ca_sg_shutdown(); +void issue_identify_client(); +void issue_identify_client_location(); +void ca_mux_io(); +int ca_select_io(); +unsigned long cacRingBufferRead(); +unsigned long cacRingBufferWrite(); +unsigned long cacRingBufferWriteSize(); +unsigned long cacRingBufferReadSize(); +char *localUserName(); +char *localLocationName(); +#endif /*__STDC__*/ -#endif +/* + * !!KLUDGE!! + * + * this was extracted from dbAccess.h because we are unable + * to include both dbAccess.h and db_access.h at the + * same time. + */ +#define S_db_Blocked (M_dbAccess|39) /*Request is Blocked*/ #endif /* this must be the last line in this file */ diff --git a/src/ca/iocmsg.h b/src/ca/iocmsg.h index ccc4dc387..6b19419d1 100644 --- a/src/ca/iocmsg.h +++ b/src/ca/iocmsg.h @@ -11,14 +11,21 @@ * SPARC alignment in db_access.h * * .04 071291 joh New command added - claim channel in use block + * + * .05 011294 joh New command added - write notify + * + * .06 020194 joh New command added for CA V4.1 - client name */ #define __IOCMSG__ -static char *iocmsghSccsId = "@(#)iocmsg.h 1.5\t7/27/92"; +static char *iocmsghSccsId = "$Id$ CA version 4.1"; /* TCP/UDP port number (bumped each protocol change) */ #define CA_PROTOCOL_VERSION 4 +#define CA_MINOR_VERSION 1 +#define CA_UKN_MINOR_VERSION 0 /* unknown minor version */ +#define CA_V41(MAJOR,MINOR) ( ((MAJOR)==4&&(MINOR)>0) || (MAJOR)>4 ) #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) @@ -27,7 +34,6 @@ static char *iocmsghSccsId = "@(#)iocmsg.h 1.5\t7/27/92"; #define MAX_TCP (MAX_UDP*16) /* so waveforms fit */ #define MAX_MSG_SIZE (MAX_TCP) /* the larger of tcp and udp max */ - /* values for m_cmmd */ #define IOC_NOOP 0 /* do nothing, but verify TCP */ #define IOC_EVENT_ADD 1 /* add an event */ @@ -50,6 +56,9 @@ static char *iocmsghSccsId = "@(#)iocmsg.h 1.5\t7/27/92"; #define IOC_READ_BUILD 16 /* read accompanying a build */ #define REPEATER_CONFIRM 17 /* registration confirmation */ #define IOC_CLAIM_CIU 18 /* client claims resource in server */ +#define IOC_WRITE_NOTIFY 19 /* notify after write chan value */ +#define IOC_CLIENT_NAME 20 /* CA V4.1 identify client */ +#define IOC_CLIENT_LOCATION 21 /* CA V4.1 identify client */ /* * for use with build and search and not_found (if search fails and @@ -59,15 +68,15 @@ static char *iocmsghSccsId = "@(#)iocmsg.h 1.5\t7/27/92"; #define DONTREPLY 5 /* size of object in bytes rounded up to nearest oct word */ -#define OCT_ROUND(A) (((A)+7)>>3) +#define OCT_ROUND(A) ((((unsigned long)A)+7)>>3) #define OCT_SIZEOF(A) (OCT_ROUND(sizeof(A))) /* size of object in bytes rounded up to nearest long word */ -#define QUAD_ROUND(A) (((A)+3)>>2) +#define QUAD_ROUND(A) (((unsigned long)A)+3)>>2) #define QUAD_SIZEOF(A) (QUAD_ROUND(sizeof(A))) /* size of object in bytes rounded up to nearest short word */ -#define BI_ROUND(A) (((A)+1)>>1) +#define BI_ROUND(A) ((((unsigned long)A)+1)>>1) #define BI_SIZEOF(A) (BI_ROUND(sizeof(A))) /* @@ -97,7 +106,6 @@ struct extmsg { * by client processes */ }; - /* * for monitor (event) message extension */ diff --git a/src/ca/net_convert.h b/src/ca/net_convert.h index a088c9aca..80094512e 100644 --- a/src/ca/net_convert.h +++ b/src/ca/net_convert.h @@ -8,11 +8,11 @@ * joh 09-13-90 force MIT sign to zero if exponent is zero * to prevent a reseved operand fault. * + * joh 03-16-94 Added double fp + * * */ -static char *net_converthSccsId = "@(#)net_convert.h 1.5\t7/27/92"; - /************************************************************************/ /* So byte swapping can be performed in line for efficiency */ /* (WINTCP has library routines with the same same functionality */ @@ -62,7 +62,7 @@ static char *net_converthSccsId = "@(#)net_convert.h 1.5\t7/27/92"; /************************************************************************/ -/* So float convert can be performed in line for efficiency */ +/* So float convert can be performed in line */ /* (THIS ASSUMES IEEE IS THE NETWORK FLOATING POINT FORMAT) */ /************************************************************************/ struct ieeeflt{ @@ -93,9 +93,9 @@ struct ieeeflt{ /* Conversion Ranges */ /* -128exp < EXPMINIEEE + MIT_SB){\ exp = 0;\ mant = 0;\ + sign = 0;\ }\ else{\ exp = (short)((struct mitflt *) (MIT))->exp-MIT_SB+IEEE_SB;\ @@ -156,199 +157,120 @@ struct ieeeflt{ # define htonf(HOST,NET) {*(float *)(NET) = *(float *)(HOST);} #endif +/************************************************************************/ +/* So double convert can be performed in line */ +/* (THIS ASSUMES IEEE IS THE NETWORK FLOATING POINT FORMAT) */ +/************************************************************************/ +struct ieeedbl{ + unsigned int mant1 : 20; + unsigned int exp : 11; + unsigned int sign : 1; + unsigned int mant2 : 32; +}; + +#define IEEE_DBL_SB 1023 + +/* Conversion Range */ +/* -1022exp < DBLEXPMINMIT + MIT_DBL_SB){\ + ((struct ieeedbl *) (IEEE))->mant1 = 0;\ + ((struct ieeedbl *) (IEEE))->mant2 = 0;\ + ((struct ieeedbl *) (IEEE))->exp = 0;\ + ((struct ieeedbl *) (IEEE))->sign = 0;\ + }\ + else{\ + ((struct ieeedbl *) (IEEE))->exp = \ + (short)((struct mitdbl *) (MIT))->exp-MIT_DBL_SB+IEEE_DBL_SB;\ + ((struct ieeedbl *) (IEEE))->mant1 = + (((struct mitdbl *) (MIT))->mant1<<13) | \ + (((struct mitdbl *) (MIT))->mant2>>3) + ((struct ieeedbl *) (IEEE))->mant2 = \ + (((struct mitdbl *) (MIT))->mant2<<29) | \ + (((struct mitdbl *) (MIT))->mant3<<13 | \ + (((struct mitdbl *) (MIT))->mant4>>3; + ((struct ieeedbl *) (IEEE))->sign = \ + ((struct mitdbl *) (MIT))->sign;\ + }\ + tmp = htonl(*(long*)(IEEE));\ + *(long *)(IEEE) = htonl(*((long*)(IEEE)+1));\ + *((long *)(IEEE)+1) = tmp;\ + } -int cvrt_sts_string( -struct dbr_sts_string *s, /* source */ -struct dbr_sts_string *d, /* destination */ -int encode, /* do VAX to IEEE */ -int num /* number of values */ -); +/* + * sign must be forced to zero if the exponent is zero to prevent a reserved + * operand fault- joh 9-13-90 + */ +# define ntohd(IEEE,MIT)\ + {\ + long tmp;\ + tmp = htonl(*(long*)(IEEE));\ + *(long *)(IEEE) = htonl(*((long*)(IEEE)+1));\ + *((long *)(IEEE)+1) = tmp;\ + if( (short)((struct ieeedbl *) (IEEE))->exp > DBLEXPMAXMIT + IEEE_DBL_SB){\ + ((struct mitdbl *) (MIT))->sign = ((struct ieeedbl *) (IEEE))->sign; \ + ((struct mitdbl *) (MIT))->exp = DBLEXPMAXMIT + MIT_DBL_SB; \ + ((struct mitdbl *) (MIT))->mant1 = ~0; \ + ((struct mitdbl *) (MIT))->mant2 = ~0; \ + ((struct mitdbl *) (MIT))->mant3 = ~0; \ + ((struct mitdbl *) (MIT))->mant4 = ~0; \ + }\ + else if( ((struct ieeedbl *) (IEEE))->exp < DBLEXPMINMIT + IEEE_DBL_SB){\ + ((struct mitdbl *) (MIT))->sign = 0; \ + ((struct mitdbl *) (MIT))->exp = 0; \ + ((struct mitdbl *) (MIT))->mant1 = 0; \ + ((struct mitdbl *) (MIT))->mant2 = 0; \ + ((struct mitdbl *) (MIT))->mant3 = 0; \ + ((struct mitdbl *) (MIT))->mant4 = 0; \ + }\ + else{\ + ((struct mitdbl *) (MIT))->sign = + ((struct ieeedbl *) (IEEE))->sign; \ + ((struct mitdbl *) (MIT))->exp = + ((struct ieeedbl *) (IEEE))->exp+MIT_DBL_SB-IEEE_DBL_SB; \ + ((struct mitdbl *) (MIT))->mant1 = + ((struct ieeedbl *) (IEEE))->mant1>>13; \ + ((struct mitdbl *) (MIT))->mant2 = + (((struct ieeedbl *) (IEEE))->mant1<<3) | + (((struct ieeedbl *) (IEEE))->mant2>>29); \ + ((struct mitdbl *) (MIT))->mant3 = + ((struct ieeedbl *) (IEEE))->mant2>>13; \ + ((struct mitdbl *) (MIT))->mant4 = + ((struct ieeedbl *) (IEEE))->mant2<<3; \ + }\ + } -int cvrt_sts_short( -struct dbr_sts_int *s, /* source */ -struct dbr_sts_int *d, /* destination */ -int encode, /* if true; vax to ieee */ -int num /* number of values */ -); - -int cvrt_sts_float( -struct dbr_sts_float *s, /* source */ -struct dbr_sts_float *d, /* destination */ -int encode, /* it true, vax to ieee */ -int num /* number of values */ -); - -int cvrt_gr_short( -struct dbr_gr_int *s, /* source */ -struct dbr_gr_int *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ -); - -int cvrt_gr_float( -struct dbr_gr_float *s, /* source */ -struct dbr_gr_float *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ -); - -int cvrt_ctrl_short( -struct dbr_ctrl_int *s, /* source */ -struct dbr_ctrl_int *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ -); - -int cvrt_ctrl_float( -struct dbr_ctrl_float *s, /* source */ -struct dbr_ctrl_float *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ -); - -int cvrt_ctrl_enum( -struct dbr_ctrl_enum *s, /* source */ -struct dbr_ctrl_enum *d, /* destination */ -int encode, /* if true, vax to ieee */ -int num /* number of values */ -); #else -int cvrt_string(); -int cvrt_short(); -int cvrt_float(); -int cvrt_enum(); -int cvrt_char(); -int cvrt_long(); -int cvrt_double(); - -int cvrt_sts_string(); -int cvrt_sts_short(); -int cvrt_sts_float(); -int cvrt_sts_enum(); -int cvrt_sts_char(); -int cvrt_sts_long(); -int cvrt_sts_double(); - -int cvrt_time_string(); -int cvrt_time_short(); -int cvrt_time_float(); -int cvrt_time_enum(); -int cvrt_time_char(); -int cvrt_time_long(); -int cvrt_time_double(); - -int cvrt_gr_string(); -int cvrt_gr_short(); -int cvrt_gr_float(); -int cvrt_gr_enum(); -int cvrt_gr_char(); -int cvrt_gr_long(); -int cvrt_gr_double(); -int cvrt_gr_string(); - -int cvrt_ctrl_string(); -int cvrt_ctrl_short(); -int cvrt_ctrl_float(); -int cvrt_ctrl_enum(); -int cvrt_ctrl_char(); -int cvrt_ctrl_long(); -int cvrt_ctrl_double(); +# define ntohd(NET,HOST) {*(double *)(HOST) = *(double *)(NET);} +# define htond(HOST,NET) {*(double *)(NET) = *(double *)(HOST);} #endif -/* cvrt is (array of) (pointer to) (function returning) int */ -static -int (*cvrt[])() - = - { - cvrt_string, - cvrt_short, - cvrt_float, - cvrt_enum, - cvrt_char, - cvrt_long, - cvrt_double, - - cvrt_sts_string, - cvrt_sts_short, - cvrt_sts_float, - cvrt_sts_enum, - cvrt_sts_char, - cvrt_sts_long, - cvrt_sts_double, - - cvrt_time_string, - cvrt_time_short, - cvrt_time_float, - cvrt_time_enum, - cvrt_time_char, - cvrt_time_long, - cvrt_time_double, - - cvrt_gr_string, - cvrt_gr_short, - cvrt_gr_float, - cvrt_gr_enum, - cvrt_gr_char, - cvrt_gr_long, - cvrt_gr_double, - - cvrt_ctrl_string, - cvrt_ctrl_short, - cvrt_ctrl_float, - cvrt_ctrl_enum, - cvrt_ctrl_char, - cvrt_ctrl_long, - cvrt_ctrl_double - }; -#endif diff --git a/src/ca/os_depen.h b/src/ca/os_depen.h index f61c5b939..a8da4a41e 100644 --- a/src/ca/os_depen.h +++ b/src/ca/os_depen.h @@ -116,16 +116,17 @@ static char *os_depenhSccsId = "@(#)os_depen.h 1.12\t2/19/93"; # define LOCKEVENTS # define UNLOCKEVENTS # define EVENTLOCKTEST (post_msg_active!=0) -# define RECV_ACTIVE(PIIU) (piiu->active) #else # if defined(vxWorks) # define VXTASKIDNONE 0 -# define LOCK FASTLOCK(&client_lock); -# define UNLOCK FASTUNLOCK(&client_lock); -# define LOCKEVENTS {FASTLOCK(&event_lock); event_tid=(int)taskIdCurrent;} -# define UNLOCKEVENTS {event_tid=VXTASKIDNONE; FASTUNLOCK(&event_lock);} -# define EVENTLOCKTEST (FASTLOCKTEST(&event_lock)&&((int)taskIdCurrent)==event_tid) -# define RECV_ACTIVE(PIIU) (ca_static->recv_tid == (int)taskIdCurrent) +# define LOCK semTake(client_lock, WAIT_FOREVER); +# define UNLOCK semGive(client_lock); +# define LOCKEVENTS \ + {semTake(event_lock, WAIT_FOREVER); event_tid=(int)taskIdCurrent;} +# define UNLOCKEVENTS \ + {event_tid=VXTASKIDNONE; semGive(event_lock);} +# define EVENTLOCKTEST \ +(((int)taskIdCurrent)==event_tid || ca_static->recv_tid == (int)taskIdCurrent) # else # if defined(UNIX) # define LOCK @@ -133,7 +134,6 @@ static char *os_depenhSccsId = "@(#)os_depen.h 1.12\t2/19/93"; # define LOCKEVENTS # define UNLOCKEVENTS # define EVENTLOCKTEST (post_msg_active!=0) -# define RECV_ACTIVE(PIIU) (piiu->active) # else @@@@ dont compile in this case @@@@ # endif @@ -143,8 +143,6 @@ static char *os_depenhSccsId = "@(#)os_depen.h 1.12\t2/19/93"; #ifdef vxWorks # define VXTHISTASKID taskIdSelf() # define abort(A) taskSuspend(VXTHISTASKID) -# define memcpy(D,S,N) bcopy(S,D,N) -# define memset(D,V,N) bfill(D,N,V) #endif diff --git a/src/ca/repeater.c b/src/ca/repeater.c index b27e4d3af..7e6b4446f 100644 --- a/src/ca/repeater.c +++ b/src/ca/repeater.c @@ -160,13 +160,9 @@ int ca_repeater_task() ca_repeater(); -#define DEBUG -# ifdef DEBUG - ca_printf("CA: Only one CA repeater thread per host\n"); -# endif -#undef DEBUG + ca_printf("%s, exiting\n", __FILE__); - return ERROR; + exit(0); } @@ -202,17 +198,17 @@ LOCAL int ca_repeater() SOL_SOCKET, SO_REUSEADDR, (char *)&true, - sizeof true); + sizeof(true)); if(status<0){ ca_printf( "%s: set socket option failed\n", __FILE__); } - memset((char *)&bd,0,sizeof bd); + memset((char *)&bd,0,sizeof(bd)); bd.sin_family = AF_INET; - bd.sin_addr.s_addr = htonl(INADDR_ANY); + bd.sin_addr.s_addr = INADDR_ANY; bd.sin_port = htons(CA_CLIENT_PORT); - status = bind(sock, (struct sockaddr *)&bd, sizeof bd); + status = bind(sock, (struct sockaddr *)&bd, sizeof(bd)); if(status<0){ if(MYERRNO != EADDRINUSE){ ca_printf("CA Repeater: unexpected bind fail %d\n", @@ -288,7 +284,7 @@ LOCAL int ca_repeater() if(!pclient){ pclient = (struct one_client *) - malloc(sizeof *pclient); + calloc(1,sizeof *pclient); if(pclient){ pclient->from = from; ellAdd( &client_list, @@ -365,7 +361,7 @@ struct one_client *pclient; memset((char *)&bd,0,sizeof bd); bd.sin_family = AF_INET; - bd.sin_addr.s_addr = htonl(INADDR_ANY); + bd.sin_addr.s_addr = INADDR_ANY; bd.sin_port = port; status = bind(sock, (struct sockaddr *)&bd, sizeof bd); if(status<0){ diff --git a/src/ca/service.c b/src/ca/service.c index 9a8961533..ff2d10ca7 100644 --- a/src/ca/service.c +++ b/src/ca/service.c @@ -98,448 +98,580 @@ static char *sccsId = "$Id$"; #ifdef __STDC__ LOCAL void reconnect_channel( -struct extmsg *hdrptr, +IIU *piiu, struct in_addr *pnet_addr ); +LOCAL int cacMsg( +struct ioc_in_use *piiu, +struct in_addr *pnet_addr +); + #else LOCAL void reconnect_channel(); +LOCAL int cacMsg(); #endif -#define BUFSTAT ca_printf("CAC: expected %d left %d\n",msgcnt,*pbufcnt); - /* * post_msg() * * + * LOCK should be applied when calling this routine * */ #ifdef __STDC__ int post_msg( -struct extmsg *hdrptr, -long *pbufcnt, +struct ioc_in_use *piiu, struct in_addr *pnet_addr, -struct ioc_in_use *piiu +char *pInBuf, +unsigned long blockSize ) #else -int post_msg(hdrptr, pbufcnt, pnet_addr, piiu) -struct extmsg *hdrptr; -long *pbufcnt; -struct in_addr *pnet_addr; +int post_msg(piiu, pnet_addr) struct ioc_in_use *piiu; +struct in_addr *pnet_addr; +char *pInBuf; +unsigned long blockSize; #endif { - evid monix; - long msgcnt; + int status; + unsigned long size; - void *t_available; - unsigned short t_postsize; - unsigned short t_cmmd; - chtype t_type; - unsigned short t_count; - int status; + while (blockSize) { + /* + * fetch a complete message header + */ + if(piiu->curMsgBytes < sizeof(piiu->curMsg)){ + char *pHdr; - post_msg_active++; + size = sizeof(piiu->curMsg) - piiu->curMsgBytes; + size = min(size, blockSize); + + pHdr = (char *) &piiu->curMsg; + memcpy( pHdr + piiu->curMsgBytes, + pInBuf, + size); + + piiu->curMsgBytes += size; + if(piiu->curMsgBytes < sizeof(piiu->curMsg)){ + return OK; + } - - while (*pbufcnt >= sizeof(*hdrptr)) { - - /* byte swap the message up front */ - t_available = (void *) hdrptr->m_available; - t_postsize = ntohs(hdrptr->m_postsize); - t_cmmd = ntohs(hdrptr->m_cmmd); - t_type = ntohs(hdrptr->m_type); - t_count = ntohs(hdrptr->m_count); - -#ifdef DEBUG - ca_printf("CAC: MSG=> cmd:%d type:%d cnt:%d npost:%d avail:%x\n", - t_cmmd, - t_type, - t_count, - t_postsize, - t_available - ); + pInBuf += size; + blockSize -= size; + + /* + * fix endian of bytes + */ + piiu->curMsg.m_postsize = + ntohs(piiu->curMsg.m_postsize); + piiu->curMsg.m_cmmd = ntohs(piiu->curMsg.m_cmmd); + piiu->curMsg.m_type = ntohs(piiu->curMsg.m_type); + piiu->curMsg.m_count = ntohs(piiu->curMsg.m_count); +#if 0 +printf("%s Cmd=%3d Type=%3d Count=%4d Size=%4d Avail=%8x Cid=%6d\n", + piiu->host_name_str, + piiu->curMsg.m_cmmd, + piiu->curMsg.m_type, + piiu->curMsg.m_count, + piiu->curMsg.m_postsize, + piiu->curMsg.m_available, + piiu->curMsg.m_cid); #endif - - msgcnt = sizeof(*hdrptr) + t_postsize; - -#ifdef DEBUG - ca_printf("CAC: bytes left %d, pending msgcnt %d\n", - *pbufcnt, - pndrecvcnt); -#endif - if (*pbufcnt < msgcnt) { - post_msg_active--; - return OK; } - switch (t_cmmd) { - case IOC_READ_NOTIFY: - { - /* - * run the user's event handler - * m_available points to event descriptor - */ - struct event_handler_args args; - - monix = (evid) t_available; - - - /* - * Currently only the VAXs need data - * conversion - */ -#ifdef VAX - (*cvrt[t_type]) ( - hdrptr + 1, - hdrptr + 1, - FALSE, - t_count); -#endif - - /* - * - * call handler, only if they did not clear the - * chid in the interim - */ - if (monix->usr_func) { - args.usr = monix->usr_arg; - args.chid = monix->chan; - args.type = t_type; - args.count = t_count; - args.dbr = (void *) (hdrptr + 1); - - LOCKEVENTS; - (*monix->usr_func) (args); - UNLOCKEVENTS; - } - LOCK; - ellDelete(&pend_read_list, &monix->node); - ellAdd(&free_event_list, &monix->node); - UNLOCK; - - piiu->outstanding_ack_count--; - - break; - } - case IOC_EVENT_ADD: - { - struct event_handler_args args; - - /* - * run the user's event handler m_available - * points to event descriptor - */ - monix = (evid) t_available; - - - /* - * m_postsize = 0 is a confirmation of a - * monitor cancel - */ - if (!t_postsize) { - LOCK; - ellDelete(&monix->chan->eventq, &monix->node); - ellAdd(&free_event_list, &monix->node); - UNLOCK; - - piiu->outstanding_ack_count--; - - break; - } - /* only call if not disabled */ - if (!monix->usr_func) - break; - - /* - * Currently only the VAXs need data - * conversion - */ -#ifdef VAX - (*cvrt[t_type]) ( - hdrptr + 1, - hdrptr + 1, - FALSE, - t_count); -#endif - - /* - * Orig version of CA didnt use this - * strucure. This would run faster if I had - * decided to pass a pointer to this - * structure rather than the structure itself - * early on. - * - * Pumping the arguments on the stack explicitly - * could cause problems if a small item is in - * the structure. - * - */ - args.usr = monix->usr_arg; - args.chid = monix->chan; - args.type = t_type; - args.count = t_count; - args.dbr = (void *) (hdrptr + 1); - - /* call their handler */ - LOCKEVENTS; - (*monix->usr_func) (args); - UNLOCKEVENTS; - - break; - } - case IOC_READ: - case IOC_READ_BUILD: - { - chid chan; - unsigned size; - - /* - * verify the channel id - */ - LOCK; - chan = bucketLookupItem(pBucket, hdrptr->m_cid); - UNLOCK; - if(!chan){ - if(t_cmmd == IOC_READ_BUILD){ - printf( - "Stale build reply from %s with id %x ignored", - host_from_addr(pnet_addr), - hdrptr->m_cid); - UNLOCK; - } - else{ - ca_signal(ECA_INTERNAL, - "bad client channel id from server"); - } - break; - } - - /* - * ignore IOC_READ_BUILDS after - * connection occurs - */ - if(t_cmmd == IOC_READ_BUILD){ - if(chan->state == cs_conn){ - break; - } - } - - /* - * only count get returns if from the current - * read seq - */ - if (!VALID_MSG(piiu)) - break; - - size = dbr_size_n(t_type, t_count); - - /* - * Currently only the VAXs need data - * conversion - */ -#ifdef VAX - (*cvrt[t_type]) ( - hdrptr + 1, - t_available, - FALSE, - t_count); -#else - memcpy( - (char *) t_available, - (char *) (hdrptr + 1), - size); -#endif - - /* - * decrement the outstanding IO count - * - * This relies on the IOC_READ_BUILD msg - * returning prior to the IOC_BUILD msg. - */ - if (t_cmmd == IOC_READ){ - piiu->outstanding_ack_count--; - CLRPENDRECV(TRUE); - } - else if(chan->connection_func == NULL && - chan->state == cs_never_conn){ - CLRPENDRECV(TRUE); - } - - - break; - } - case IOC_SEARCH: - case IOC_BUILD: - reconnect_channel(hdrptr, pnet_addr); - break; - - case IOC_READ_SYNC: - piiu->outstanding_ack_count--; - piiu->read_seq++; - break; - - case IOC_RSRV_IS_UP: - LOCK; - { - struct in_addr ina; - - ina.s_addr = (long) t_available; - mark_server_available(&ina); - } - UNLOCK; - break; - - case REPEATER_CONFIRM: - ca_static->ca_repeater_contacted = TRUE; -#ifdef DEBUG - ca_printf("CAC: repeater confirmation recv\n"); -#endif - break; - - case IOC_NOT_FOUND: - break; - - case IOC_CLEAR_CHANNEL: - { - chid chix = (chid) t_available; - struct ioc_in_use *piiu = chix->piiu; - register evid monix; - - - LOCK; - /* - * remove any orphaned get callbacks for this - * channel - */ - for (monix = (evid) pend_read_list.node.next; - monix; - monix = (evid) monix->node.next) - if (monix->chan == chix) { - ellDelete( - &pend_read_list, - &monix->node); - ellAdd( - &free_event_list, - &monix->node); - } - ellConcat(&free_event_list, &chix->eventq); - ellDelete(&piiu->chidlist, &chix->node); - status = bucketRemoveItem(pBucket, chix->cid, chix); - if(status != BUCKET_SUCCESS){ - ca_signal( - ECA_INTERNAL, - "bad id at channel delete"); - } - free(chix); - piiu->outstanding_ack_count--; - if (!piiu->chidlist.count){ - close_ioc(piiu); - } - UNLOCK; - break; - } - case IOC_ERROR: - { - char context[255]; - char *name; - struct extmsg *req = hdrptr + 1; - int op; - struct exception_handler_args args; - - - /* - * dont process the message if they have - * disable notification - */ - if (!ca_static->ca_exception_func){ - break; - } - - name = (char *) host_from_addr(pnet_addr); - if (!name){ - name = "an unregistered IOC"; - } - - if (t_postsize > sizeof(struct extmsg)){ - sprintf(context, - "detected by: %s for: %s", - name, - (char *)(hdrptr + 2)); - } - else{ - sprintf(context, "detected by: %s", name); - } - - /* - * Map internal op id to external op id so I - * can freely change the protocol in the - * future. This is quite wasteful of space - * however. - */ - switch (ntohs(req->m_cmmd)) { - case IOC_READ_NOTIFY: - case IOC_READ: - op = CA_OP_GET; - break; - case IOC_WRITE: - op = CA_OP_PUT; - break; - case IOC_SEARCH: - case IOC_BUILD: - op = CA_OP_SEARCH; - break; - case IOC_EVENT_ADD: - op = CA_OP_ADD_EVENT; - break; - case IOC_EVENT_CANCEL: - op = CA_OP_CLEAR_EVENT; - break; - default: - op = CA_OP_OTHER; - break; - } - - LOCK; - args.chid = bucketLookupItem(pBucket, hdrptr->m_cid); - UNLOCK; - args.usr = ca_static->ca_exception_arg; - args.type = ntohs(req->m_type); - args.count = ntohs(req->m_count); - args.addr = (void *) (req->m_available); - args.stat = ntohl((int) t_available); args.op = op; - args.ctx = context; - - LOCKEVENTS; - (*ca_static->ca_exception_func) (args); - UNLOCKEVENTS; - break; - } - default: - ca_printf("CAC: post_msg(): Corrupt cmd in msg %x\n", - t_cmmd); - - *pbufcnt = 0; - post_msg_active--; + /* + * dont allow huge msg body until + * the server supports it + */ + if(piiu->curMsg.m_postsize>(unsigned)MAX_TCP){ + piiu->curMsgBytes = 0; + piiu->curDataBytes = 0; return ERROR; } - *pbufcnt -= msgcnt; - hdrptr = (struct extmsg *) (msgcnt + (char *) hdrptr); + /* + * make sure we have a large enough message body cache + */ + if(piiu->curMsg.m_postsize>piiu->curDataMax){ + if(piiu->pCurData){ + free(piiu->pCurData); + } + piiu->curDataMax = 0; + piiu->pCurData = (void *) + malloc(piiu->curMsg.m_postsize); + if(!piiu->pCurData){ + piiu->curMsgBytes = 0; + piiu->curDataBytes = 0; + return ERROR; + } + piiu->curDataMax = + piiu->curMsg.m_postsize; + } + /* + * Fetch a complete message body + */ + if(piiu->curMsg.m_postsize>piiu->curDataBytes){ + char *pBdy; + + size = piiu->curMsg.m_postsize - piiu->curDataBytes; + size = min(size, blockSize); + pBdy = piiu->pCurData; + memcpy( pBdy+piiu->curDataBytes, + pInBuf, + size); + piiu->curDataBytes += size; + if(piiu->curDataBytes < piiu->curMsg.m_postsize){ + return OK; + } + pInBuf += size; + blockSize -= size; + } + + + /* + * execute the response message + */ + status = cacMsg(piiu, pnet_addr); + piiu->curMsgBytes = 0; + piiu->curDataBytes = 0; + if(status != OK){ + return ERROR; + } } + return OK; +} - if(piiu->outstanding_ack_count == 0){ - piiu->bytes_pushing_an_ack = 0; +#ifdef __STDC__ +LOCAL int cacMsg( +struct ioc_in_use *piiu, +struct in_addr *pnet_addr +) +#else +LOCAL int cacMsg(piiu, pnet_addr) +struct ioc_in_use *piiu; +struct in_addr *pnet_addr; +#endif +{ + evid monix; + int status; + + switch (piiu->curMsg.m_cmmd) { + + case IOC_NOOP: + break; + + case IOC_WRITE_NOTIFY: + { + /* + * run the user's event handler + * m_available points to event descriptor + */ + struct event_handler_args args; + + monix = (evid) piiu->curMsg.m_available; + + /* + * + * call handler, only if they did not clear the + * chid in the interim + */ + if (monix->usr_func) { + args.usr = monix->usr_arg; + args.chid = monix->chan; + args.type = monix->type; + args.count = monix->count; + args.dbr = NULL; + /* + * the channel id field is abused for + * write notify status + * + * write notify was added vo CA V4.1 + */ + args.status = ntohl(piiu->curMsg.m_cid); + + LOCKEVENTS; + (*monix->usr_func) (args); + UNLOCKEVENTS; + } + LOCK; + ellDelete(&pend_write_list, &monix->node); + ellAdd(&free_event_list, &monix->node); + UNLOCK; + + break; + + } + case IOC_READ_NOTIFY: + { + /* + * run the user's event handler + * m_available points to event descriptor + */ + struct event_handler_args args; + + monix = (evid) piiu->curMsg.m_available; + + /* + * + * call handler, only if they did not clear the + * chid in the interim + */ + if (monix->usr_func) { + int v41; + + /* + * convert the data buffer from net + * format to host format + * + * Currently only the VAXs need data + * conversion + */ +# ifdef VAX + (*cvrt[piiu->curMsg.m_type])( + piiu->pCurData, + piiu->pCurData, + FALSE, + piiu->curMsg.m_count); +# endif + + args.usr = monix->usr_arg; + args.chid = monix->chan; + args.type = piiu->curMsg.m_type; + args.count = piiu->curMsg.m_count; + args.dbr = piiu->pCurData; + /* + * the channel id field is abused for + * read notify status starting + * with CA V4.1 + */ + v41 = CA_V41( + CA_PROTOCOL_VERSION, + piiu->minor_version_number); + if(v41){ + args.status = ntohl(piiu->curMsg.m_cid); + } + else{ + args.status = ECA_NORMAL; + } + + LOCKEVENTS; + (*monix->usr_func) (args); + UNLOCKEVENTS; + } + LOCK; + ellDelete(&pend_read_list, &monix->node); + ellAdd(&free_event_list, &monix->node); + UNLOCK; + + break; } + case IOC_EVENT_ADD: + { + int v41; + struct event_handler_args args; - post_msg_active--; + /* + * run the user's event handler m_available + * points to event descriptor + */ + monix = (evid) piiu->curMsg.m_available; + + + /* + * m_postsize = 0 is a confirmation of a + * monitor cancel + */ + if (!piiu->curMsg.m_postsize) { + LOCK; + ellDelete(&monix->chan->eventq, &monix->node); + ellAdd(&free_event_list, &monix->node); + UNLOCK; + + break; + } + /* only call if not disabled */ + if (!monix->usr_func) + break; + + /* + * convert the data buffer from net + * format to host format + * + * Currently only the VAXs need data + * conversion + */ +# ifdef VAX + (*cvrt[piiu->curMsg.m_type])( + piiu->pCurData, + piiu->pCurData, + FALSE, + piiu->curMsg.m_count); +# endif + + /* + * Orig version of CA didnt use this + * strucure. This would run faster if I had + * decided to pass a pointer to this + * structure rather than the structure itself + * early on. + */ + args.usr = monix->usr_arg; + args.chid = monix->chan; + args.type = piiu->curMsg.m_type; + args.count = piiu->curMsg.m_count; + args.dbr = piiu->pCurData; + /* + * the channel id field is abused for + * event status starting + * with CA V4.1 + */ + v41 = CA_V41( + CA_PROTOCOL_VERSION, + piiu->minor_version_number); + if(v41){ + args.status = ntohl(piiu->curMsg.m_cid); + } + else{ + args.status = ECA_NORMAL; + } + + /* call their handler */ + LOCKEVENTS; + (*monix->usr_func) (args); + UNLOCKEVENTS; + + break; + } + case IOC_READ: + case IOC_READ_BUILD: + { + chid chan; + + /* + * verify the channel id + */ + LOCK; + chan = bucketLookupItem(pBucket, piiu->curMsg.m_cid); + UNLOCK; + if(!chan){ + if(piiu->curMsg.m_cmmd != IOC_READ_BUILD){ + ca_signal(ECA_INTERNAL, + "bad client channel id from server"); + } + break; + } + + /* + * ignore IOC_READ_BUILDS after + * connection occurs + */ + if(piiu->curMsg.m_cmmd == IOC_READ_BUILD){ + if(chan->state == cs_conn || + chan->state == cs_closed){ + break; + } + } + + /* + * only count get returns if from the current + * read seq + */ + if (!VALID_MSG(piiu)) + break; + + /* + * convert the data buffer from net + * format to host format + * + * Currently only the VAXs need data + * conversion + */ +# ifdef VAX + (*cvrt[piiu->curMsg.m_type])( + piiu->pCurData, + piiu->pCurData, + FALSE, + piiu->curMsg.m_count); +# else + memcpy( + (char *)piiu->curMsg.m_available, + piiu->pCurData, + dbr_size_n(piiu->curMsg.m_type, piiu->curMsg.m_count)); +# endif + + /* + * decrement the outstanding IO count + * + * This relies on the IOC_READ_BUILD msg + * returning prior to the IOC_BUILD msg. + */ + if (piiu->curMsg.m_cmmd == IOC_READ){ + CLRPENDRECV(TRUE); + } + else if(chan->connection_func == NULL && + chan->state == cs_never_conn){ + CLRPENDRECV(TRUE); + } + + break; + } + case IOC_SEARCH: + case IOC_BUILD: + reconnect_channel(piiu, pnet_addr); + break; + + case IOC_READ_SYNC: + piiu->read_seq++; + break; + + case IOC_RSRV_IS_UP: + LOCK; + { + struct in_addr ina; + + ina.s_addr = (long) piiu->curMsg.m_available; + mark_server_available(&ina); + } + UNLOCK; + break; + + case REPEATER_CONFIRM: + ca_static->ca_repeater_contacted = TRUE; +#ifdef DEBUG + ca_printf("CAC: repeater confirmation recv\n"); +#endif + break; + + case IOC_NOT_FOUND: + break; + + case IOC_CLEAR_CHANNEL: + { + chid chix = (chid) piiu->curMsg.m_available; + struct ioc_in_use *piiu = chix->piiu; + register evid monix; + + + LOCK; + /* + * remove any orphaned get callbacks for this + * channel + */ + for (monix = (evid) pend_read_list.node.next; + monix; + monix = (evid) monix->node.next){ + if (monix->chan == chix) { + ellDelete( + &pend_read_list, + &monix->node); + ellAdd( + &free_event_list, + &monix->node); + } + } + ellConcat(&free_event_list, &chix->eventq); + ellDelete(&piiu->chidlist, &chix->node); + status = bucketRemoveItem(pBucket, chix->cid, chix); + if(status != BUCKET_SUCCESS){ + ca_signal( + ECA_INTERNAL, + "bad id at channel delete"); + } + free(chix); + if (!piiu->chidlist.count){ + piiu->conn_up = FALSE; + } + UNLOCK; + break; + } + case IOC_ERROR: + { + char nameBuf[64]; + char context[255]; + struct extmsg *req = piiu->pCurData; + int op; + struct exception_handler_args args; + + + /* + * dont process the message if they have + * disable notification + */ + if (!ca_static->ca_exception_func){ + break; + } + + host_from_addr(pnet_addr, nameBuf, sizeof(nameBuf)); + + if (piiu->curMsg.m_postsize > sizeof(struct extmsg)){ + sprintf(context, + "detected by: %s for: %s", + nameBuf, + (char *)(req+1)); + } + else{ + sprintf(context, "detected by: %s", nameBuf); + } + + /* + * Map internal op id to external op id so I + * can freely change the protocol in the + * future. This is quite wasteful of space + * however. + */ + switch (ntohs(req->m_cmmd)) { + case IOC_READ_NOTIFY: + case IOC_READ: + op = CA_OP_GET; + break; + case IOC_WRITE_NOTIFY: + case IOC_WRITE: + op = CA_OP_PUT; + break; + case IOC_SEARCH: + case IOC_BUILD: + op = CA_OP_SEARCH; + break; + case IOC_EVENT_ADD: + op = CA_OP_ADD_EVENT; + break; + case IOC_EVENT_CANCEL: + op = CA_OP_CLEAR_EVENT; + break; + default: + op = CA_OP_OTHER; + break; + } + + LOCK; + args.chid = bucketLookupItem(pBucket, piiu->curMsg.m_cid); + UNLOCK; + args.usr = ca_static->ca_exception_arg; + args.type = ntohs(req->m_type); + args.count = ntohs(req->m_count); + args.addr = (void *) (req->m_available); + args.stat = ntohl((long) piiu->curMsg.m_available); args.op = op; + args.ctx = context; + + LOCKEVENTS; + (*ca_static->ca_exception_func) (args); + UNLOCKEVENTS; + break; + } + default: + ca_printf("CAC: post_msg(): Corrupt cmd in msg %x\n", + piiu->curMsg.m_cmmd); + + return ERROR; + } return OK; } @@ -547,27 +679,28 @@ struct ioc_in_use *piiu; /* * - * RECONNECT_CHANNEL() - * LOCK must be on + * reconnect_channel() * */ #ifdef __STDC__ LOCAL void reconnect_channel( -struct extmsg *hdrptr, +IIU *piiu, struct in_addr *pnet_addr ) #else LOCAL void reconnect_channel(hdrptr,pnet_addr) -struct extmsg *hdrptr; +IIU *piiu; struct in_addr *pnet_addr; #endif { + char rej[64]; chid chan; evid pevent; int status; enum channel_state prev_cs; IIU *allocpiiu; IIU *chpiiu; + unsigned short *pMinorVersion; /* * ignore broadcast replies for deleted channels @@ -577,14 +710,8 @@ struct in_addr *pnet_addr; LOCK; chan = bucketLookupItem( pBucket, - hdrptr->m_available); + piiu->curMsg.m_available); if(!chan){ - sprintf( - sprintf_buf, - "Search reply from %s with server id %x", - host_from_addr(pnet_addr), - hdrptr->m_available); - ca_signal(ECA_NOCHANMSG, sprintf_buf); UNLOCK; return; } @@ -597,6 +724,17 @@ struct in_addr *pnet_addr; return; } + /* + * Ignore search replies to closing channels + */ + if(chan->state == cs_closed) { + UNLOCK; + return; + } + + /* + * Ignore duplicate search replies + */ if (chan->state == cs_conn) { if (chpiiu->sock_addr.sin_addr.s_addr == @@ -606,36 +744,16 @@ struct in_addr *pnet_addr; fflush(stdout); # endif } else { - char acc[128]; - char rej[128]; - sprintf(acc, - "%s", - chpiiu->host_name_str); - sprintf(rej, - "%s", - host_from_addr(pnet_addr)); + host_from_addr(pnet_addr,rej,sizeof(rej)); sprintf( sprintf_buf, "Channel: %s Accepted: %s Rejected: %s ", (char *)(chan + 1), - acc, + chpiiu->host_name_str, rej); ca_signal(ECA_DBLCHNL, sprintf_buf); } -# ifdef IOC_READ_FOLLOWING_BUILD - /* - * IOC_BUILD messages always have a - * IOC_READ msg following. (IOC_BUILD - * messages are sometimes followed by - * error messages which are ignored - * on double replies) - */ - if (t_cmmd == IOC_BUILD){ - msgcnt += sizeof(struct extmsg) + - ntohs((hdrptr + 1)->m_postsize); - } -# endif UNLOCK; return; } @@ -645,19 +763,31 @@ struct in_addr *pnet_addr; IPPROTO_TCP, &allocpiiu); if(status != ECA_NORMAL){ - ca_printf( "CAC: ... %s ...\n", ca_message(status)); - ca_printf( "CAC: for %s on %s\n", - chan+1, - host_from_addr(pnet_addr)); - ca_printf( "CAC: ignored search reply- proceeding\n"); + host_from_addr(pnet_addr,rej,sizeof(rej)); + ca_printf("CAC: ... %s ...\n", ca_message(status)); + ca_printf("CAC: for %s on %s\n", chan+1, rej); + ca_printf("CAC: ignored search reply- proceeding\n"); UNLOCK; return; } /* Update rmt chid fields from extmsg fields */ - chan->type = ntohs(hdrptr->m_type); - chan->count = ntohs(hdrptr->m_count); - chan->id.sid = hdrptr->m_cid; + chan->type = piiu->curMsg.m_type; + chan->count = piiu->curMsg.m_count; + chan->id.sid = piiu->curMsg.m_cid; + + /* + * Starting with CA V4.1 the minor version number + * is appended to the end of each search reply. + * This value is ignored by earlier clients. + */ + if(piiu->curMsg.m_postsize >= sizeof(*pMinorVersion)){ + pMinorVersion = (unsigned short *)(piiu->pCurData); + allocpiiu->minor_version_number = ntohs(*pMinorVersion); + } + else{ + allocpiiu->minor_version_number = CA_UKN_MINOR_VERSION; + } if(chpiiu != allocpiiu){ @@ -669,6 +799,17 @@ struct in_addr *pnet_addr; ellDelete(&chpiiu->chidlist, &chan->node); chan->piiu = chpiiu = allocpiiu; ellAdd(&chpiiu->chidlist, &chan->node); + + /* + * If this is the first channel to be + * added to this IIU then communicate + * the client's name to the server. + * (CA V4.1 or higher) + */ + if(ellCount(&chpiiu->chidlist)==1){ + issue_identify_client(chpiiu); + issue_identify_client_location(chpiiu); + } } /* @@ -727,6 +868,7 @@ struct in_addr *pnet_addr; CLRPENDRECV(TRUE); } + UNLOCK; } @@ -743,7 +885,7 @@ void cac_io_done(lock) int lock; #endif { - register struct pending_io_event *pioe; + struct pending_io_event *pioe; if(ioeventlist.count==0) return; diff --git a/src/ca/syncgrp.c b/src/ca/syncgrp.c index f72bcb04b..29a9a10af 100644 --- a/src/ca/syncgrp.c +++ b/src/ca/syncgrp.c @@ -36,9 +36,15 @@ */ #include "assert.h" +#include "string.h" #include "db_access.h" #include "iocinf.h" +#ifdef vxWorks +#include +#include +#endif + #define CASG_MAGIC 0xFAB4CAFE /* @@ -73,9 +79,9 @@ typedef struct{ }CASG; #ifdef __STDC__ -static void io_complete(struct event_handler_args args); +LOCAL void io_complete(struct event_handler_args args); #else /*__STDC__*/ -static void io_complete(); +LOCAL void io_complete(); #endif /*__STDC__*/ @@ -93,8 +99,6 @@ void ca_sg_init() */ ellInit(&ca_static->activeCASG); ellInit(&ca_static->freeCASG); - ellInit(&ca_static->activeCASGOP); - ellInit(&ca_static->freeCASGOP); return; } @@ -113,10 +117,10 @@ struct ca_static *ca_temp; /* * free all sync group lists */ - ellFree(&ca_static->activeCASG); - ellFree(&ca_static->freeCASG); - ellInit(&ca_static->activeCASGOP); - ellInit(&ca_static->freeCASGOP); + ellFree(&ca_temp->activeCASG); + ellFree(&ca_temp->freeCASG); + ellInit(&ca_temp->activeCASGOP); + ellInit(&ca_temp->freeCASGOP); return; } @@ -285,15 +289,15 @@ float timeout; UNLOCK; return ECA_BADSYNCGRP; } + UNLOCK; /* * always flush and take care * of connection management * at least once. */ + ca_flush_io(); manage_conn(TRUE); - cac_send_msg(); - UNLOCK; status = ECA_NORMAL; beg_time = time(NULL); @@ -307,11 +311,12 @@ float timeout; itimeout.tv_usec = LOCALTICKS; itimeout.tv_sec = 0; - LOCK; - recv_msg_select(&itimeout); - UNLOCK; + ca_mux_io(&itimeout, CA_DO_SENDS|CA_DO_RECVS); } +#else /*UNIX*/ + ca_flush_io(); #endif /*UNIX*/ + #ifdef vxWorks { semTake(pcasg->sem, LOCALTICKS); @@ -342,18 +347,8 @@ float timeout; status = ECA_TIMEOUT; break; } - - /* - * flush and take care of conn - * management prior to each time - * that we pend - */ - LOCK; manage_conn(TRUE); - cac_send_msg(); - UNLOCK; } - UNLOCK; pcasg->opPendCount = 0; pcasg->seqNo++; return status; @@ -460,7 +455,6 @@ void *pvalue; return ECA_ALLOCMEM; } } - UNLOCK; memset(pcasgop, 0,sizeof(*pcasgop)); pcasgop->id = gid; @@ -468,6 +462,7 @@ void *pvalue; pcasgop->magic = CASG_MAGIC; pcasgop->pValue = NULL; /* handler will know its a put */ ellAdd(&ca_static->activeCASGOP, &pcasgop->node); + UNLOCK; status = ca_array_put_callback( type, @@ -523,7 +518,6 @@ void *pvalue; return ECA_ALLOCMEM; } } - UNLOCK; memset(pcasgop, 0,sizeof(*pcasgop)); pcasgop->id = gid; @@ -532,6 +526,8 @@ void *pvalue; pcasgop->pValue = pvalue; ellAdd(&ca_static->activeCASGOP, &pcasgop->node); + UNLOCK; + status = ca_array_get_callback( type, count, @@ -546,9 +542,9 @@ void *pvalue; * io_complete() */ #ifdef __STDC__ -static void io_complete(struct event_handler_args args) +LOCAL void io_complete(struct event_handler_args args) #else /*__STDC__*/ -static void io_complete(args) +LOCAL void io_complete(args) struct event_handler_args args; #endif /*__STDC__*/ { @@ -579,8 +575,9 @@ struct event_handler_args args; if(!(args.status&CA_M_SUCCESS)){ ca_printf( - "CA Sync Group (id=%d) operation failed because \"%s\"\n", + "CA Sync Group (id=%d) operation failed because %d \"%s\"\n", pcasgop->id, + args.status, ca_message(args.status)); UNLOCK; return; diff --git a/src/ca/test_event.c b/src/ca/test_event.c index fccdad001..71540cddc 100644 --- a/src/ca/test_event.c +++ b/src/ca/test_event.c @@ -34,6 +34,12 @@ struct event_handler_args args; ca_printf("CAC: User argument\t%x\n", args.usr); ca_printf("CAC: Native channel data type\t%d\n", args.chid->type); ca_printf("CAC: Monitor data type\t%d\n", args.type); + ca_printf("CAC: CA Status \"%s\"\n", ca_message(args.status)); + + if(!args.dbr || !(CA_M_SUCCESS&args.status)){ + return; + } + switch(args.type){ case DBR_STRING: ca_printf("CAC: Value:\t<%s>\n",args.dbr);