sun4 support added

This commit is contained in:
Jeff Hill
1991-06-27 16:02:21 +00:00
parent 6fc3be2422
commit c6e8557a86
18 changed files with 3394 additions and 2741 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -13,16 +13,15 @@
#include <cadef.h>
#include <db_access.h>
/*
#define CA_TEST_CHNL "AI_T2000"
*/
#define CA_TEST_CHNL "ca:ai_2000"
#define CA_TEST_CHNL4 "ca:ai_2000"
#define CA_TEST_CHNL4 "ca:bo_000"
#define EVENT_ROUTINE null_event
/*
#define EVENT_ROUTINE ca_test_event
#define CONN_ROUTINE NULL
*/
#define EVENT_ROUTINE null_event
#define CONN_ROUTINE conn
#define NUM 1
@@ -50,6 +49,7 @@ main()
void ca_test_event();
void null_event();
struct dbr_gr_float *ptr;
struct dbr_gr_float *pgrfloat;
float delay = .003;
long status;
@@ -60,6 +60,7 @@ main()
char string[41];
float value;
float *pfloat;
double *pdouble;
struct dbr_ctrl_float *pctrl;
char pstring[NUM][MAX_STRING_SIZE];
void write_event();
@@ -92,7 +93,7 @@ main()
0,
&chix4,
NULL,
conn,
CONN_ROUTINE,
NULL),NULL);
SEVCHK(ca_build_and_connect(
CA_TEST_CHNL,
@@ -100,7 +101,7 @@ main()
0,
&chix2,
NULL,
conn,
CONN_ROUTINE,
NULL),NULL);
SEVCHK(ca_build_and_connect(
CA_TEST_CHNL,
@@ -108,7 +109,7 @@ main()
0,
&chix1,
NULL,
conn,
CONN_ROUTINE,
NULL),NULL);
status = ca_pend_io(10.0);
SEVCHK(status,NULL);
@@ -137,7 +138,7 @@ main()
0,
&chix4,
NULL,
conn,
CONN_ROUTINE,
NULL),NULL);
SEVCHK(ca_build_and_connect(
CA_TEST_CHNL,
@@ -145,7 +146,7 @@ main()
0,
&chix2,
NULL,
conn,
CONN_ROUTINE,
NULL),NULL);
SEVCHK(ca_build_and_connect(
CA_TEST_CHNL,
@@ -153,10 +154,10 @@ main()
0,
&chix1,
NULL,
conn,
CONN_ROUTINE,
NULL),NULL);
status = ca_pend_io(1.0);
status = ca_pend_io(10.0);
SEVCHK(status,NULL);
if(INVALID_DB_REQ(chix1->type))
@@ -190,6 +191,8 @@ main()
status = ca_add_event(DBR_FLOAT, chix4, EVENT_ROUTINE, 0xaaaaaaaa, &monix);
SEVCHK(status,NULL);
SEVCHK(ca_clear_event(monix),NULL);
status = ca_add_event(DBR_FLOAT, chix4, EVENT_ROUTINE, 0xaaaaaaaa, &monix);
SEVCHK(status,NULL);
}
if(VALID_DB_REQ(chix4->type)){
status = ca_add_event(DBR_FLOAT, chix4, EVENT_ROUTINE, 0xaaaaaaaa, &monix);
@@ -206,6 +209,8 @@ main()
pfloat = (float *) malloc(sizeof(float)*NUM);
pdouble = (double *) malloc(sizeof(double)*NUM);
pgrfloat = (struct dbr_gr_float *) malloc(sizeof(*pgrfloat)*NUM);
if(VALID_DB_REQ(chix1->type))
@@ -215,6 +220,8 @@ main()
sprintf(&pstring[j][0],"%d",j+100);
SEVCHK(ca_array_put(DBR_STRING,NUM,chix1,pstring),NULL)
SEVCHK(ca_array_get(DBR_FLOAT,NUM,chix1,pfloat),NULL)
SEVCHK(ca_array_get(DBR_DOUBLE,NUM,chix1,pdouble),NULL)
SEVCHK(ca_array_get(DBR_GR_FLOAT,NUM,chix1,pgrfloat),NULL)
}
else
abort();
@@ -224,18 +231,22 @@ main()
# ifdef VMS
lib$show_timer();
# endif
for(i=0;i<NUM;i++)
printf("Value Returned from put/get %f\n",pfloat[i]);
for(i=0;i<NUM;i++){
printf("Float value Returned from put/get %f\n",pfloat[i]);
printf("Double value Returned from put/get %f\n",pdouble[i]);
printf("GR Float value Returned from put/get %f\n",pgrfloat[i].value);
}
for(i=0;i<10;i++)
ca_get_callback(DBR_FLOAT, chix1, ca_test_event, NULL);
ca_get_callback(DBR_GR_FLOAT, chix1, ca_test_event, NULL);
printf("-- Put/Gets done- waiting for Events --\n");
status = ca_pend_event(500.0);
status = ca_pend_event(60.0);
if(status == ECA_TIMEOUT){
free(ptr);
free(pfloat);
free(pgrfloat);
exit();
}else
@@ -251,8 +262,8 @@ void null_event()
{
static int i;
if(i++>100){
printf("100 occured\n");
if(i++>1000){
printf("1000 occured\n");
i = 0;
}
}

View File

@@ -9,17 +9,15 @@
/* */
/* History */
/* ------- */
/* */
/* Date Programmer Comments */
/* ---- ---------- -------- */
/* 6/89 Jeff Hill Init Release */
/* .00 06xx89 joh Init Release */
/* .01 060591 joh delinting */
/* */
/*_begin */
/************************************************************************/
/* */
/* Title: IOC connection automation */
/* File: atcs:[ca]conn.c */
/* Environment: VMS, UNIX, VRTX */
/* Environment: VMS, UNIX, vxWorks */
/* Equipment: VAX, SUN, VME */
/* */
/* */
@@ -36,10 +34,11 @@
#include <iocmsg.h>
#include <iocinf.h>
/*
*
* CHID_RETRY
* MANAGE_CONN
*
* retry disconnected channels
*
@@ -47,29 +46,45 @@
* NOTES:
* Lock must be applied while in this routine
*/
chid_retry(silent)
void manage_conn(silent)
char silent;
{
register chid chix;
register unsigned int retry_cnt = 0;
register unsigned int keepalive_cnt = 0;
unsigned int retry_cnt_no_handler = 0;
char string[100];
char string[128];
ca_time current;
int i;
int search_type;
/*
* CASTTMO+pndrecvcnt*LKUPTMO)/DELAYVAL + 1
*/
#define CASTTMO 0.150 /* 150 mS */
#define LKUPTMO 0.015 /* 15 mS */
current = time(NULL);
for(i=0; i< nxtiiu; i++){
if(i != BROADCAST_IIU && iiu[i].conn_up)
int search_type;
if(iiu[i].next_retry > current)
continue;
/*
* periodic keepalive on unused channels
*/
if(i != BROADCAST_IIU && iiu[i].conn_up){
/*
* reset of delay to the next keepalive
* occurs when the message is sent
*/
noop_msg(&iiu[i]);
keepalive_cnt++;
continue;
}
if(iiu[i].nconn_tries++ > MAXCONNTRIES)
continue;
iiu[i].retry_delay += iiu[i].retry_delay;
iiu[i].next_retry = current + iiu[i].retry_delay;
search_type = (i==BROADCAST_IIU? DONTREPLY: DOREPLY);
chix = (chid) &iiu[i].chidlist;
@@ -80,14 +95,13 @@ char silent;
retry_cnt++;
if(!(silent || chix->connection_func)){
ca_signal(ECA_CHIDNOTFND, chix+1);
ca_signal(ECA_CHIDNOTFND, chix+1);
retry_cnt_no_handler++;
}
}
}
if(retry_cnt){
send_msg();
printf("<Trying> ");
#ifdef UNIX
fflush(stdout);
@@ -99,7 +113,10 @@ char silent;
}
}
return ECA_NORMAL;
if(keepalive_cnt|retry_cnt){
cac_send_msg();
}
}
@@ -115,49 +132,96 @@ char silent;
*
*/
void
mark_server_available(net_addr)
struct in_addr net_addr;
mark_server_available(pnet_addr)
struct in_addr *pnet_addr;
{
int i;
void noop_msg();
unsigned port;
int i;
/*
* if timers have expired take care of them
* before they are reset
*/
manage_conn(TRUE);
#ifdef DEBUG
printf("<%s> ",host_from_addr(pnet_addr));
#ifdef UNIX
fflush(stdout);
#endif
#endif
for(i=0;i<nxtiiu;i++)
if( (net_addr.s_addr ==
if( (pnet_addr->s_addr ==
iiu[i].sock_addr.sin_addr.s_addr)){
/*
* reset the retry count out
*
*/
iiu[i].nconn_tries = 0;
/*
* Check if the conn is down but TCP
* has not informed me by sending a NULL msg
*/
if(iiu[i].conn_up){
/*
* Check if the conn is down but TCP
* has not informed me by sending a NULL msg
*/
noop_msg(&iiu[i]);
send_msg();
cac_send_msg();
}
else{
/*
* reset the delay to the next retry
*/
iiu[i].next_retry = CA_CURRENT_TIME;
iiu[i].nconn_tries = 0;
iiu[i].retry_delay = 1;
manage_conn(TRUE);
}
return;
}
/*
* Not on a known IOC so try a directed UDP
* never connected to this IOC before
*
* We end up here when the client starts before the server
*
* It would be best if this used a directed UDP
* reply rather than a broadcast
*/
/*
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This connects when the client starts before the server
1) uses a broadcast- should use a directed UDP messaage
2) many clients with nonexsistent channels could
cause a flood here
/*
* reset the retry cnt to 3
*/
iiu[BROADCAST_IIU].nconn_tries = MAXCONNTRIES-3;
/*
* This part is very important since many machines
* could have channels in a disconnected state which
* dont exist anywhere on the network. This insures
* that we dont have many CA clients synchronously
* flooding the network with broadcasts.
*
* I fetch the local port number and use the low order bits
* as a pseudo random delay to prevent every one
* from replying at once.
*/
{
struct sockaddr_in saddr;
unsigned saddr_length = sizeof(saddr);
int status;
status = getsockname(
iiu[BROADCAST_IIU].sock_chan,
&saddr,
&saddr_length);
if(status<0)
abort();
port = saddr.sin_port;
}
iiu[BROADCAST_IIU].retry_delay = (port&0xf) + 1;
iiu[BROADCAST_IIU].next_retry = time(NULL) + iiu[BROADCAST_IIU].retry_delay;
#ifdef DEBUG
printf("<Trying ukn online after pseudo random delay=%d sec> ",
iiu[BROADCAST_IIU].retry_delay);
#ifdef UNIX
fflush(stdout);
#endif
#endif
iiu[BROADCAST_IIU].nconn_tries = MAXCONNTRIES-1;
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/
}

View File

@@ -9,10 +9,8 @@
/* */
/* History */
/* ------- */
/* */
/* Date Programmer Comments */
/* ---- ---------- -------- */
/* 6/89 Jeff Hill Init Release */
/* 06xx89 joh First Release */
/* 060591 joh delinting */
/* */
/*_begin */
/************************************************************************/
@@ -47,38 +45,46 @@
#include <iocmsg.h>
#include <iocinf.h>
/*
Keep track of how many times messages have come with out a break in between
*/
* FLOW CONTROL
*
* Keep track of how many times messages have
* come with out a break in between and
* suppress monitors if we are behind
* (an update is sent when we catch up)
*/
void
flow_control(piiu)
struct ioc_in_use *piiu;
{
unsigned nbytes;
register int status;
register int busy = piiu->client_busy;
struct ioc_in_use *piiu;
{
unsigned nbytes;
register int status;
register int busy = piiu->client_busy;
status = socket_ioctl( piiu->sock_chan,
FIONREAD,
&nbytes);
if(status < 0)
return ERROR;
status = socket_ioctl(piiu->sock_chan,
FIONREAD,
&nbytes);
if (status < 0) {
close_ioc(piiu);
return;
}
if(nbytes){
piiu->contiguous_msg_count++;
if(!busy)
if(piiu->contiguous_msg_count > MAX_CONTIGUOUS_MSG_COUNT){
piiu->client_busy = TRUE;
ca_busy_message(piiu);
}
}
else{
piiu->contiguous_msg_count=0;
if(busy){
ca_ready_message(piiu);
piiu->client_busy = FALSE;
}
}
if (nbytes) {
piiu->contiguous_msg_count++;
if (!busy)
if (piiu->contiguous_msg_count >
MAX_CONTIGUOUS_MSG_COUNT) {
piiu->client_busy = TRUE;
ca_busy_message(piiu);
}
} else {
piiu->contiguous_msg_count = 0;
if (busy) {
ca_ready_message(piiu);
piiu->client_busy = FALSE;
}
}
return;
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,11 +9,9 @@
/* */
/* History */
/* ------- */
/* */
/* Date Programmer Comments */
/* ---- ---------- -------- */
/* 8/87 Jeff Hill Init Release */
/* 1/90 Jeff Hill fd_set in the UNIX version only */
/* .01 08xx87 joh Init Release */
/* .02 01xx90 joh fd_set in the UNIX version only */
/* .03 060691 joh Rearanged buffer struct for SPARC port */
/* */
/*_begin */
/************************************************************************/
@@ -60,7 +58,6 @@
# include <os_depen.h>
#endif
void send_msg();
/* throw out requests prior to last ECA_TIMEOUT from ca_pend */
#define VALID_MSG(PIIU) (piiu->read_seq == piiu->cur_read_seq)
@@ -87,25 +84,13 @@ enum channel_state{cs_never_conn, cs_prev_conn, cs_conn, closed};
#define SETPENDRECV {pndrecvcnt++;}
#define CLRPENDRECV {if(--pndrecvcnt<1){IODONESUB; POST_IO_EV;}}
/* size of object in bytes rounded up to nearest long word */
#define QUAD_ROUND(A) (((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_SIZEOF(A) (QUAD_ROUND(sizeof(A)))
/*
#define MAX(A,B) (((A)>(B))?(A):(B))
#define MIN(A,B) (((A)>(B))?(B):(A))
*/
/************************************************************************/
/* Structures */
/************************************************************************/
/* stk must be above and contiguous with buf ! */
struct buffer{
unsigned long stk;
char buf[MAX_MSG_SIZE]; /* from iocmsg.h */
unsigned long stk;
};
@@ -121,6 +106,9 @@ struct pending_io_event{
void *io_done_arg;
};
typedef unsigned long ca_time;
#define CA_RETRY_PERIOD 5 /* sec to next keepalive */
#define CA_CURRENT_TIME 0
#define MAX_CONTIGUOUS_MSG_COUNT 2
@@ -148,15 +136,16 @@ struct pending_io_event{
#define io_done_flag (ca_static->ca_io_done_flag)
#define evuser (ca_static->ca_evuser)
#define client_lock (ca_static->ca_client_lock)
#define event_buf (ca_static->ca_event_buf)
#define event_buf_size (ca_static->ca_event_buf_size)
#define local_chidlist (ca_static->ca_local_chidlist)
#define dbfree_ev_list (ca_static->ca_dbfree_ev_list)
#define lcl_buff_list (ca_static->ca_lcl_buff_list)
#endif
#ifdef VMS
#define io_done_flag (ca_static->ca_io_done_flag)
#define peek_ast_buf (ca_static->ca_peek_ast_buf)
#endif
struct ca_static{
unsigned short ca_nxtiiu;
long ca_pndrecvcnt;
@@ -166,7 +155,7 @@ struct ca_static{
void (*ca_connection_func)();
void *ca_connection_arg;
void (*ca_fd_register_func)();
void (*ca_fd_register_arg)();
void *ca_fd_register_arg;
short ca_exit_in_progress;
unsigned short ca_post_msg_active;
LIST ca_free_event_list;
@@ -177,16 +166,16 @@ struct ca_static{
#endif
#ifdef VMS
int ca_io_done_flag;
char ca_peek_ast_buf;
#endif
#ifdef vxWorks
int ca_io_done_flag;
void *ca_evuser;
FAST_LOCK ca_client_lock;
void *ca_event_buf;
unsigned ca_event_buf_size;
int ca_tid;
LIST ca_local_chidlist;
LIST ca_dbfree_ev_list;
LIST ca_lcl_buff_list;
#endif
struct ioc_in_use{
unsigned contiguous_msg_count;
@@ -200,10 +189,10 @@ struct ca_static{
unsigned read_seq;
unsigned cur_read_seq;
LIST chidlist; /* chans on this connection */
unsigned nconn_wait; /* number delays before try */
unsigned nconn_tries; /* number of times conn was tried */
int conn_up; /* boolean: T-conn /F-disconn */
unsigned count_to_refresh; /* ndelays to conn retry */
unsigned nconn_tries;
ca_time next_retry;
ca_time retry_delay;
#define MAXCONNTRIES 3
#ifdef VMS /* for qio ASTs */
struct sockaddr_in recvfrom;
@@ -236,12 +225,21 @@ struct ca_static{
GLBLTYPE
struct ca_static *ca_static;
#ifdef VMS
GLBLTYPE
char ca_unique_address;
# define MYTIMERID (&ca_unique_address)
#endif
/*
* CA internal functions
*
*/
void cac_send_msg();
void build_msg();
struct in_addr broadcast_addr();
void manage_conn();
void noop_msg();
void ca_busy_message();
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();
#endif

View File

@@ -1,18 +1,21 @@
#ifndef __IOCMSG__
/*
History
1/90 joh removed status field in favor of a seperate command-
saves space on every successful operation
4-13-90 joh moved server ports to above IPPORT_USERRESERVED
see in.h
*/
* History
* .01 01xx90 joh removed status field in favor of a independent m_cmmd-
* saves space on every successful operation
*
* .02 041390 joh moved server ports to above IPPORT_USERRESERVED
* see in.h
*
* .03 060391 joh Bumped protocol version to 4 to support changes for
* SPARC alignment in db_access.h
*
*/
#define __IOCMSG__
/* TCP/UDP port number (bumped each protocol change) */
#define CA_PROTOCOL_VERSION 3
#define CA_PROTOCOL_VERSION 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)
@@ -23,7 +26,6 @@
/* values for m_cmmd */
#define IOC_NOOP 0 /* do nothing, but verify TCP */
#define IOC_EVENT_ADD 1 /* add an event */
#define IOC_EVENT_CANCEL 2 /* cancel an event */
@@ -45,20 +47,42 @@
#define IOC_READ_BUILD 16 /* read accompanying a build */
#define REPEATER_CONFIRM 17 /* registration confirmation */
/*
for use with build and search and not_found
(if search fails and its not a broadcast tell
the client to look elesewhere)
*/
/*
* for use with build and search and not_found (if search fails and
* its not a broadcast tell the client to look elesewhere)
*/
#define DOREPLY 10
#define DONTREPLY 5
/* extmsg - the nonvariant part of each message sent/recv
by the request server.
*/
/* size of object in bytes rounded up to nearest oct word */
#define OCT_ROUND(A) (((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_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_SIZEOF(A) (BI_ROUND(sizeof(A)))
/*
* Required Message Alignment
*
* Determined by the architecture with the most restrictive
* alignment requirements (currently the SPARC).
*
* octal rounding
*
* NOTE: all structures declared in this file must have a
* byte count which is evenly divisible by 8 for the SPARC.
*/
#define CA_MESSAGE_ALIGN(A) (OCT_ROUND(A)<<3)
/*
* the common part of each message sent/recv by the
* CA server.
*/
struct extmsg {
unsigned short m_cmmd; /* operation to be performed */
unsigned short m_postsize; /* size of message extension */
@@ -70,7 +94,9 @@ struct extmsg {
};
/* for monitor (event) message extension */
/*
* for monitor (event) message extension
*/
struct mon_info{
float m_lval; /* low delta */
float m_hval; /* high delta */

View File

@@ -96,15 +96,17 @@ extern int taskIdCurrent;
#ifdef VMS
struct iosb{
short status;
unsigned short count;
void *device;
short status;
unsigned short count;
void *device;
};
static char ca_unique_address;
#define MYTIMERID (&ca_unique_address)
#endif
struct timeval{
unsigned long tv_sec;
unsigned long tv_usec;
unsigned long tv_sec;
unsigned long tv_usec;
};
#ifdef vxWorks
@@ -137,15 +139,19 @@ struct timeval{
#endif
#ifdef vxWorks
# define SYSFREQ sysClkRateGet() /* 60 Hz */
# define TCPDELAY taskDelay((unsigned int)DELAYVAL*SYSFREQ);
# define time(A) (tickGet()/sysfreq)
# define SYSFREQ sysClkRateGet() /* usually 60 Hz */
# define TCPDELAY taskDelay((unsigned int)DELAYVAL*SYSFREQ);
# define time(A) (tickGet()/SYSFREQ)
#endif
#ifdef UNIX
# define SYSFREQ 1000000 /* 1 MHz */
# define TCPDELAY {if(select(0,NULL,NULL,NULL,&tcpdelayval)<0)abort();}
static struct timeval tcpdelayval = {0,(unsigned int)DELAYVAL*SYSFREQ};
# define SYSFREQ 1000000 /* 1 MHz */
# define TCPDELAY {if(select(0,NULL,NULL,NULL,&tcpdelayval)<0)abort();}
# ifndef CA_GLBLSOURCE
extern struct timeval tcpdelayval;
# else
struct timeval tcpdelayval = {0,(unsigned int)DELAYVAL*SYSFREQ};
# endif
#endif

View File

@@ -36,18 +36,24 @@
*
* This server does not gaurantee the reliability of
* fanned out broadcasts in keeping with the nature of
* broadcasts. Therefore, CA provides a backup.
* broadcasts. Therefore, CA retransmitts lost msgs.
*
* UDP datagrams delivered between two processes on the same
* machine dont travel over the LAN.
*
*
* Modification Log:
* -----------------
* Modification Log:
* -----------------
* .01 060691 joh Took out 4 byte count at message begin to
* in preparation for SPARC alignment
*
*/
#include <vxWorks.h>
#include <lstLib.h>
#ifdef VMS
#include <stsdef.h>
#endif
#include <errno.h>
#include <types.h>
@@ -60,9 +66,9 @@
struct sockaddr_in *local_addr();
/*
these can be external since there is only one instance
per machine so we dont care about reentrancy
*/
* these can be external since there is only one instance
* per machine so we dont care about reentrancy
*/
struct one_client{
NODE node;
struct sockaddr_in from;
@@ -72,9 +78,13 @@ static
LIST client_list;
static
char buf[MAX_UDP]; /* bigger than max TCP */
char buf[MAX_UDP];
int ca_repeater();
#define NTRIES 100
/*
*
* Fan out broadcasts to several processor local tasks
@@ -86,6 +96,38 @@ main()
#else
ca_repeater_task()
#endif
{
unsigned i,j;
/*
*
* This allows the system inet support to takes it
* time releasing the bind I used to test if the repeater
* is up.
*
*/
for(i=0; i<NTRIES; i++){
ca_repeater();
for(j=0; j<100; j++)
TCPDELAY;
#ifdef DEBUG
printf("CA: retiring the repeater\n");
#endif
}
printf("CA: Only one CA repeater thread per host\n");
return ERROR;
}
/*
*
* ca_repeater()
*
*
*/
ca_repeater()
{
int status;
int size;
@@ -96,7 +138,6 @@ ca_repeater_task()
int from_size = sizeof from;
struct one_client *pclient;
struct one_client *pnxtclient;
unsigned *pcount = (unsigned *)buf;
lstInit(&client_list);
@@ -106,23 +147,28 @@ ca_repeater_task()
SOCK_DGRAM, /* type */
0); /* deflt proto */
if(sock == ERROR)
abort();
return FALSE;
memset(&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, &bd, sizeof bd);
if(status<0)
if(MYERRNO == EADDRINUSE){
printf("Only one CA repeater thread per host\n");
exit();
if(status<0){
if(MYERRNO != EADDRINUSE){
printf("CA REepeater: unexpected bind fail %d\n",
MYERRNO);
}
else
abort();
socket_close(sock);
return FALSE;
}
local = *local_addr(sock);
#ifdef DEBUG
printf("CA Repeater: Attached and initialized\n");
#endif
while(TRUE){
size = recvfrom(
@@ -134,9 +180,7 @@ ca_repeater_task()
&from_size);
if(size > 0){
if(size != ntohl(*pcount))
printf("ca repeater: corrupt msg ignored\n");
else if(from.sin_addr.s_addr != local.sin_addr.s_addr)
if(from.sin_addr.s_addr != local.sin_addr.s_addr)
for( pclient = (struct one_client *)
client_list.node.next;
pclient;
@@ -150,18 +194,17 @@ ca_repeater_task()
0,
&pclient->from,
sizeof pclient->from);
if(status < 0)
abort();
if(status < 0){
printf("CA Repeater: fanout err %d\n",
MYERRNO);
}
#ifdef DEBUG
printf("Sent\n");
#endif
}
}
else if(size == 0){
struct {
unsigned length;
struct extmsg extmsg;
}confirm;
struct extmsg confirm;
/*
* If this is a processor local message then add to
@@ -189,9 +232,8 @@ ca_repeater_task()
}
memset(&confirm, NULL, sizeof confirm);
confirm.length = htonl(sizeof confirm);
confirm.extmsg.m_cmmd = htons(REPEATER_CONFIRM);
confirm.extmsg.m_available = local.sin_addr.s_addr;
confirm.m_cmmd = htons(REPEATER_CONFIRM);
confirm.m_available = local.sin_addr.s_addr;
status = sendto(
sock,
&confirm,
@@ -199,10 +241,15 @@ ca_repeater_task()
0,
&from, /* reflect back to sender */
sizeof from);
if(status != sizeof confirm)
abort();
}else
abort();
if(status != sizeof confirm){
printf("CA Repeater: confirm err %d\n",
MYERRNO);
}
}
else{
printf("CA Repeater: recv err %d\n",
MYERRNO);
}
/* remove any dead wood prior to pending */
for( pclient = (struct one_client *)
@@ -217,7 +264,7 @@ ca_repeater_task()
}
}
/*
*
* check to see if this client is still around
@@ -236,8 +283,11 @@ struct one_client *pclient;
sock = socket( AF_INET, /* domain */
SOCK_DGRAM, /* type */
0); /* deflt proto */
if(sock == ERROR)
abort();
if(sock == ERROR){
printf("CA Repeater: no socket err %d\n",
MYERRNO);
return ERROR;
}
memset(&bd,0,sizeof bd);
bd.sin_family = AF_INET;
@@ -247,10 +297,12 @@ struct one_client *pclient;
if(status<0){
if(MYERRNO == EADDRINUSE)
present = TRUE;
else
abort();
else{
printf("CA Repeater: client cleanup err %d\n",
MYERRNO);
}
}
close(sock);
socket_close(sock);
if(!present){
lstDelete(&client_list, pclient);

View File

@@ -10,11 +10,17 @@
/* History */
/* ------- */
/* */
/* Date Programmer Comments */
/* ---- ---------- -------- */
/* 8/87 Jeff Hill Init Release */
/* 1/90 Jeff Hill Made cmmd for errors which */
/* Date Person Comments */
/* ---- ------ -------- */
/* 8/87 joh Init Release */
/* 1/90 joh Made cmmd for errors which */
/* eliminated the status field */
/* 030791 joh Fixed problem where pend count was decremented */
/* prior to connecting chan (setting the type). */
/* 041591 joh added call to channel exsits routine */
/* 060491 joh fixed structure pass for SPARC cc */
/* 060691 jow reworked to remove 4 byte count before each */
/* macro message */
/* */
/*_begin */
/************************************************************************/
@@ -55,420 +61,477 @@
#include <iocinf.h>
void reconnect_channel();
#define BUFSTAT printf("expected %d left %d\n",msgcnt,*pbufcnt);
void post_msg(hdrptr,bufcnt,net_addr,piiu)
register struct extmsg *hdrptr;
register long bufcnt;
struct in_addr net_addr;
struct ioc_in_use *piiu;
/*
* post_msg()
*
*
*
*/
void
post_msg(hdrptr, pbufcnt, pnet_addr, piiu)
register struct extmsg *hdrptr;
register unsigned long *pbufcnt;
struct in_addr *pnet_addr;
struct ioc_in_use *piiu;
{
evid monix;
long msgcnt;
long tmp;
evid monix;
long msgcnt;
register void * t_available;
register unsigned short t_postsize;
register unsigned short t_cmmd;
register chtype t_type;
register unsigned short t_count;
register unsigned short t_size;
int status;
register void *t_available;
register unsigned short t_postsize;
register unsigned short t_cmmd;
register chtype t_type;
register unsigned short t_count;
int status;
# define BUFSTAT\
printf("expected %d left %d\n",msgcnt,bufcnt);
post_msg_active++;
post_msg_active++;
while(bufcnt>0){
# ifdef DEBUG
printf( "processing message- bytes left %d, pending msgcnt %d\n",
bufcnt,
pndrecvcnt);
# endif
/* 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);
t_size = dbr_size[t_type];
# ifdef DEBUG
printf( "MSG: cmd:%d type:%d cnt:%d size:%d npost:%d avail:%x\n",
t_cmmd,
t_type,
t_count,
t_size,
t_postsize,
t_available
);
# endif
msgcnt = sizeof(*hdrptr) + t_postsize;
if(bufcnt-msgcnt < 0){
printf(
"post_msg(): expected msg size larger than actual msg %d %d\n",
bufcnt,
msgcnt);
post_msg_active--;
return;
}
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
/*
* 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 and we are on a SPARC processor.
*
* 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);
(*monix->usr_func)(args);
}
LOCK;
lstDelete(&pend_read_list, monix);
lstAdd(&free_event_list, monix);
UNLOCK;
break;
}
case IOC_EVENT_ADD:
{
/* run the user's event handler */
/* m_available points to event descriptor */
struct event_handler_args args;
monix = (evid) t_available;
/* m_postsize = 0 is a confirmation of a monitor cancel */
if( !t_postsize ){
LOCK;
lstDelete(&monix->chan->eventq, monix);
lstAdd(&free_event_list, monix);
UNLOCK;
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 and we are on a SPARC processor.
*
*/
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 */
(*monix->usr_func)(args);
break;
}
case IOC_READ:
case IOC_READ_BUILD:
{
chid chan = (chid) hdrptr->m_pciu;
/* only count get returns if from the current read seq */
if(!VALID_MSG(piiu))
break;
if(t_postsize > (t_count-1) * dbr_value_size[t_type] + dbr_size[t_type])
SEVCHK(ECA_INTERNAL,"about to violate user's buffer");
/*
* Currently only the VAXs need data conversion
*/
# ifdef VAX
(*cvrt[t_type])( hdrptr+1, t_available, FALSE, t_count);
# else
/* in line is a little faster */
if(t_postsize<=sizeof(int)){
if(t_postsize==sizeof(long))
*(long *)t_available = *(long *)(hdrptr+1);
else if(t_postsize==sizeof(short))
*(short *)t_available = *(short *)(hdrptr+1);
else if(t_postsize==sizeof(char))
*(char *)t_available = *(char *)(hdrptr+1);
}else
memcpy(
t_available,
hdrptr+1,
t_postsize);
# 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_BUILD ||
(chan->connection_func == NULL && chan->state==cs_never_conn))
CLRPENDRECV;
break;
}
case IOC_SEARCH:
case IOC_BUILD:
{
chid chan = (chid) t_available;
struct ioc_in_use *chpiiu = &iiu[chan->iocix];
if( chan->paddr ){
if(chpiiu->sock_addr.sin_addr.s_addr==net_addr.s_addr){
printf("burp ");
#ifdef UNIX
fflush(stdout);
while (*pbufcnt >= sizeof(*hdrptr)) {
#ifdef DEBUG
printf("bytes left %d, pending msgcnt %d\n",
*pbufcnt,
pndrecvcnt);
#endif
}
else{
char msg[256];
char acc[64];
char rej[64];
sprintf(acc,"%s",
host_from_addr(chpiiu->sock_addr.sin_addr));
sprintf(rej,"%s",host_from_addr(net_addr));
sprintf(
msg,
/* 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
printf("MSG: cmd:%d type:%d cnt:%d npost:%d avail:%x\n",
t_cmmd,
t_type,
t_count,
t_postsize,
t_available
);
#endif
msgcnt = sizeof(*hdrptr) + t_postsize;
if (*pbufcnt < msgcnt) {
post_msg_active--;
return;
}
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);
(*monix->usr_func) (args);
}
LOCK;
lstDelete(&pend_read_list, monix);
lstAdd(&free_event_list, monix);
UNLOCK;
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;
lstDelete(&monix->chan->eventq, monix);
lstAdd(&free_event_list, monix);
UNLOCK;
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 */
(*monix->usr_func) (args);
break;
}
case IOC_READ:
case IOC_READ_BUILD:
{
chid chan = (chid) hdrptr->m_pciu;
unsigned size;
/*
* 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
/*
* in line is a little faster
*/
switch(size){
case sizeof(char):
*(char *) t_available =
*(char *) (hdrptr + 1);
break;
case sizeof(short):
*(short *) t_available =
*(short *) (hdrptr + 1);
break;
case sizeof(long):
*(long *) t_available =
*(long *) (hdrptr + 1);
break;
case sizeof(double):
*(double *) t_available =
*(double *) (hdrptr + 1);
break;
default:
memcpy(
t_available,
hdrptr + 1,
size);
break;
}
#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_BUILD ||
(chan->connection_func == NULL &&
chan->state == cs_never_conn))
CLRPENDRECV;
break;
}
case IOC_SEARCH:
case IOC_BUILD:
{
chid chan = (chid) t_available;
struct ioc_in_use *chpiiu;
/*
* ignore broadcast replies for deleted channels
*
*/
LOCK;
status = client_channel_exists(chan);
UNLOCK;
if (!status) {
char msg[64];
sprintf(
msg,
"Search reply from %s",
host_from_addr(pnet_addr));
ca_signal(ECA_NOCHANMSG,msg);
break;
}
chpiiu = &iiu[chan->iocix];
if (chan->paddr) {
if (chpiiu->sock_addr.sin_addr.s_addr ==
pnet_addr->s_addr) {
printf("<Extra> ");
#ifdef UNIX
fflush(stdout);
#endif
} else {
char msg[256];
char acc[64];
char rej[64];
sprintf(acc,
"%s",
host_from_addr(
&chpiiu->sock_addr.sin_addr));
sprintf(rej,
"%s",
host_from_addr(pnet_addr));
sprintf(
msg,
"Channel: %s Accepted: %s Rejected: %s ",
chan+1,
acc,
rej);
ca_signal(ECA_DBLCHNL, msg);
chan + 1,
acc,
rej);
ca_signal(ECA_DBLCHNL, msg);
}
/*
* IOC_BUILD messages allways 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) +
(hdrptr + 1)->m_postsize;
break;
}
reconnect_channel(hdrptr, 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) t_available;
mark_server_available(&ina);
}
UNLOCK;
break;
case REPEATER_CONFIRM:
ca_static->ca_repeater_contacted = TRUE;
#ifdef DEBUG
printf("repeater confirmation recv\n");
#endif
break;
case IOC_NOT_FOUND:
{
chid chix = (chid) t_available;
struct ioc_in_use *piiu = &iiu[chix->iocix];
LOCK;
lstDelete(&piiu->chidlist, chix);
lstAdd(&iiu[BROADCAST_IIU].chidlist, chix);
chix->iocix = BROADCAST_IIU;
if (!piiu->chidlist.count)
close_ioc(piiu);
/*
* reset the delay to the next retry or keepalive
*/
piiu->next_retry = CA_CURRENT_TIME;
piiu->nconn_tries = 0;
manage_conn(TRUE);
UNLOCK;
break;
}
/*
* IOC_BUILD messages allways 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) +
(hdrptr+1)->m_postsize;
break;
}
case IOC_CLEAR_CHANNEL:
{
chid chix = (chid) t_available;
struct ioc_in_use *piiu = &iiu[chix->iocix];
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) {
lstDelete(&pend_read_list, monix);
lstAdd(&free_event_list, monix);
}
lstConcat(&free_event_list, &chix->eventq);
lstDelete(&piiu->chidlist, chix);
if (free(chix) < 0)
abort();
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,
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;
}
args.usr = ca_static->ca_exception_arg;
args.chid = (chid) hdrptr->m_pciu;
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;
(*ca_static->ca_exception_func) (args);
break;
}
default:
printf("post_msg(): Corrupt Cmd in msg %x\n",
t_cmmd);
abort();
}
*pbufcnt -= msgcnt;
hdrptr = (struct extmsg *) (msgcnt + (char *) hdrptr);
if(!chan->connection_func && chan->state==cs_never_conn){
/* decrement the outstanding IO count */
CLRPENDRECV;
}
LOCK;
reconnect_channel(hdrptr,net_addr,piiu);
UNLOCK;
if(chan->connection_func){
struct connection_handler_args args;
post_msg_active--;
args.chid = chan;
args.op = CA_OP_CONN_UP;
(*chan->connection_func)(args);
}
break;
}
case IOC_READ_SYNC:
piiu->read_seq++;
break;
case IOC_RSRV_IS_UP:
# ifdef DEBUG
printf( "IOC on line ->[%s]\n",
host_from_addr(t_available));
# endif
LOCK;
mark_server_available(t_available);
chid_retry(TRUE);
UNLOCK;
break;
case REPEATER_CONFIRM:
ca_static->ca_repeater_contacted = TRUE;
# ifdef DEBUG
printf("repeater confirmation\n");
# endif
break;
case IOC_NOT_FOUND:
{
chid chix = (chid) t_available;
struct ioc_in_use *piiu = &iiu[chix->iocix];
LOCK;
lstDelete(&piiu->chidlist, chix);
lstAdd(&iiu[BROADCAST_IIU].chidlist, chix);
chix->iocix = BROADCAST_IIU;
if(!piiu->chidlist.count)
close_ioc(piiu);
iiu[BROADCAST_IIU].nconn_tries = 0;
chid_retry(TRUE);
UNLOCK;
break;
}
case IOC_CLEAR_CHANNEL:
{
chid chix = (chid) t_available;
struct ioc_in_use *piiu = &iiu[chix->iocix];
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){
lstDelete(&pend_read_list, monix);
lstAdd(&free_event_list, monix);
}
lstConcat(&free_event_list, &chix->eventq);
lstDelete(&piiu->chidlist, chix);
if(free(chix)<0)
abort();
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(net_addr);
if(!name)
name = "an unregistered IOC";
if(t_postsize>sizeof(struct extmsg))
sprintf(context, "detected by: %s for: %s", name, 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;
}
args.usr = ca_static->ca_exception_arg; /* user arg */
args.chid = hdrptr->m_pciu; /* the chid if appropriate */
args.type = ntohs(req->m_type); /* req type if approp */
args.count = ntohs(req->m_count); /* req count if approp */
args.addr = (void *) (req->m_available);/* req user addr if approp */
args.stat = ntohl((int)t_available); /* the CA message code */
args.op = op; /* the CA operation */
args.ctx = context; /* context string */
(*ca_static->ca_exception_func)(args);
break;
}
default:
printf("post_msg(): Corrupt Cmd in msg %x\n",t_cmmd);
abort();
}
bufcnt -= msgcnt;
hdrptr = (struct extmsg *) (msgcnt + (char *) hdrptr);
}
post_msg_active--;
}
}
/*
@@ -477,10 +540,9 @@ if(t_postsize > (t_count-1) * dbr_value_size[t_type] + dbr_size[t_type])
* LOCK must be on
*
*/
void reconnect_channel(hdrptr,net_addr,piiu)
static void reconnect_channel(hdrptr,pnet_addr)
register struct extmsg *hdrptr;
struct in_addr net_addr;
struct ioc_in_use *piiu;
struct in_addr *pnet_addr;
{
chid chan = (chid) hdrptr->m_available;
unsigned short newiocix;
@@ -489,15 +551,17 @@ struct ioc_in_use *piiu;
void ca_request_event();
LOCK;
status = alloc_ioc (
net_addr,
pnet_addr,
IPPROTO_TCP,
&newiocix
);
if(status != ECA_NORMAL){
printf("... %s ...\n", ca_message(status));
printf("for %s on %s\n", chan+1, host_from_addr(net_addr));
printf("ignored broadcast reply- proceeding\n");
printf("for %s on %s\n", chan+1, host_from_addr(pnet_addr));
printf("ignored search reply- proceeding\n");
return;
}
@@ -531,7 +595,7 @@ struct ioc_in_use *piiu;
pevent = (evid) pevent->node.next)
if(pevent->chan == chan){
issue_get_callback(pevent);
send_msg();
cac_send_msg();
}
}
#endif
@@ -542,8 +606,23 @@ struct ioc_in_use *piiu;
pevent;
pevent = (evid)pevent->node.next)
ca_request_event(pevent);
send_msg();
cac_send_msg();
}
UNLOCK;
if(chan->connection_func){
struct connection_handler_args args;
args.chid = chan;
args.op = CA_OP_CONN_UP;
(*chan->connection_func)(args);
}
else if(chan->state==cs_never_conn){
/* decrement the outstanding IO count */
CLRPENDRECV;
}
chan->state = cs_conn;
}

View File

@@ -1,3 +1,18 @@
/*
*
* T E S T _ E V E N T . C
* Author: Jeffrey O. Hill
* simple stub for testing monitors
*
*
* History
* joh 031891 printed type in decimanl instead of hex
*
*
*
*
*/
/* System includes */
#include <cadef.h>
@@ -8,22 +23,33 @@ void
ca_test_event(args)
struct event_handler_args args;
{
printf("~~~### in test event for [%s] ###~~~\n",args.chid+1);
printf("User argument\t%x\n", args.usr);
printf("Native channel data type\t%x\n", args.chid->type);
printf("Monitor data type\t%x\n", args.type);
printf("Native channel data type\t%d\n", args.chid->type);
printf("Monitor data type\t%d\n", args.type);
switch(args.type){
case DBR_STRING:
printf("Value:\t<%s>\n",args.dbr);
break;
case DBR_CHAR:
printf("Value:\t<%d>\n",*(char *)args.dbr);
break;
#if DBR_INT != DBR_SHORT
case DBR_INT:
#endif
case DBR_SHORT:
case DBR_ENUM:
printf("Value:\t<%d>\n",*(int *)args.dbr);
printf("Value:\t<%d>\n",*(short *)args.dbr);
break;
case DBR_LONG:
printf("Value:\t<%d>\n",*(long *)args.dbr);
break;
case DBR_FLOAT:
printf("Value:\t<%f>\n",*(float *)args.dbr);
break;
case DBR_DOUBLE:
printf("Value:\t<%f>\n",*(double *)args.dbr);
break;
case DBR_STS_STRING:
printf("Value:\t<%s>\n",((struct dbr_sts_string *)args.dbr)->value);
break;
@@ -39,7 +65,6 @@ struct event_handler_args args;
case DBR_GR_FLOAT:
printf("Value:\t<%f>\n",((struct dbr_gr_float *)args.dbr)->value);
break;
default:
printf( "Sorry test_event does not handle data type %d yet\n",
args.type);

View File

@@ -29,7 +29,7 @@
*
* Modification Log:
* -----------------
* .01 mm-dd-yy iii Comment
* .01 06-25-91 joh inserted the RISC aligned db_access.h structures
*/
@@ -110,28 +110,16 @@
/* function declarations */
/*
* database access address structure
*/
#include <db_addr.h>
/* database access address structure (removed from db_access.h and put here) */
struct db_addr{
char *precord; /* record number of specified type */
char *pfield; /* offset from the record origin */
char *pad0; /* not used by old */
short pad1; /*not used by old */
short no_elements; /* number of elements in arrays of data */
short record_type; /* type of record being accessed */
short pad2; /* not used by old */
short field_size; /* size of the field being accessed */
/* from database for values of waveforms */
short special; /* special processing */
short choice_set; /* index of choiceSet GBLCHOICE & RECCHOICE*/
short field_type; /* field type as seen by database request*/
/*DBR_STRING,...,DBR_ENUM,DBR_NOACCESS*/
};
/* structures for old database access */
#ifndef MAX_STRING_SIZE
#define MAX_STRING_SIZE 40
#endif
/* VALUES WITH STATUS STRUCTURES */
/* structure for a string status field */
@@ -169,9 +157,10 @@ struct dbr_sts_enum{
/* structure for a char status field */
struct dbr_sts_char{
short status; /* status of value */
short severity; /* severity of alarm */
unsigned char value; /* current value */
short status; /* status of value */
short severity; /* severity of alarm */
char RISC_pad; /* RISC alignment */
unsigned char value; /* current value */
};
/* structure for a long status field */
@@ -185,6 +174,7 @@ struct dbr_sts_long{
struct dbr_sts_double{
short status; /* status of value */
short severity; /* severity of alarm */
long RISC_pad; /* RISC alignment */
double value; /* current value */
};
@@ -203,6 +193,7 @@ struct dbr_time_short{
short status; /* status of value */
short severity; /* severity of alarm */
TS_STAMP stamp; /* time stamp */
short RISC_pad; /* RISC alignment */
short value; /* current value */
};
@@ -219,6 +210,7 @@ struct dbr_time_enum{
short status; /* status of value */
short severity; /* severity of alarm */
TS_STAMP stamp; /* time stamp */
short RISC_pad; /* RISC alignment */
short value; /* current value */
};
@@ -227,6 +219,8 @@ struct dbr_time_char{
short status; /* status of value */
short severity; /* severity of alarm */
TS_STAMP stamp; /* time stamp */
short RISC_pad0; /* RISC alignment */
char RISC_pad1; /* RISC alignment */
unsigned char value; /* current value */
};
@@ -243,6 +237,7 @@ struct dbr_time_double{
short status; /* status of value */
short severity; /* severity of alarm */
TS_STAMP stamp; /* time stamp */
long RISC_pad; /* RISC alignment */
double value; /* current value */
};
@@ -282,6 +277,7 @@ struct dbr_gr_float{
short status; /* status of value */
short severity; /* severity of alarm */
short precision; /* number of decimal places */
short RISC_pad0; /* RISC alignment */
char units[8]; /* units of value */
float upper_disp_limit; /* upper limit of graph */
float lower_disp_limit; /* lower limit of graph */
@@ -303,16 +299,17 @@ struct dbr_gr_enum{
/* structure for a graphic char field */
struct dbr_gr_char{
short status; /* status of value */
short severity; /* severity of alarm */
char units[8]; /* units of value */
unsigned char upper_disp_limit; /* upper limit of graph */
unsigned char lower_disp_limit; /* lower limit of graph */
unsigned char upper_alarm_limit;
unsigned char upper_warning_limit;
unsigned char lower_warning_limit;
unsigned char lower_alarm_limit;
unsigned char value; /* current value */
short status; /* status of value */
short severity; /* severity of alarm */
char units[8]; /* units of value */
unsigned char upper_disp_limit; /* upper limit of graph */
unsigned char lower_disp_limit; /* lower limit of graph */
unsigned char upper_alarm_limit;
unsigned char upper_warning_limit;
unsigned char lower_warning_limit;
unsigned char lower_alarm_limit;
char RISC_pad; /* RISC alignment */
unsigned char value; /* current value */
};
/* structure for a graphic long field */
@@ -334,6 +331,7 @@ struct dbr_gr_double{
short status; /* status of value */
short severity; /* severity of alarm */
short precision; /* number of decimal places */
short RISC_pad0; /* RISC alignment */
char units[8]; /* units of value */
double upper_disp_limit; /* upper limit of graph */
double lower_disp_limit; /* lower limit of graph */
@@ -384,6 +382,7 @@ struct dbr_ctrl_float{
short status; /* status of value */
short severity; /* severity of alarm */
short precision; /* number of decimal places */
short RISC_pad; /* RISC alignment */
char units[8]; /* units of value */
float upper_disp_limit; /* upper limit of graph */
float lower_disp_limit; /* lower limit of graph */
@@ -418,6 +417,7 @@ struct dbr_ctrl_char{
unsigned char lower_alarm_limit;
unsigned char upper_ctrl_limit; /* upper control limit */
unsigned char lower_ctrl_limit; /* lower control limit */
char RISC_pad; /* RISC alignment */
unsigned char value; /* current value */
};
@@ -442,6 +442,7 @@ struct dbr_ctrl_double{
short status; /* status of value */
short severity; /* severity of alarm */
short precision; /* number of decimal places */
short RISC_pad0; /* RISC alignment */
char units[8]; /* units of value */
double upper_disp_limit; /* upper limit of graph */
double lower_disp_limit; /* lower limit of graph */
@@ -455,6 +456,8 @@ struct dbr_ctrl_double{
};
/* From $cs/dblib/src/dbiocsubs.c
* subroutines

View File

@@ -41,7 +41,6 @@
#include <db_access.h>
#include <task_params.h>
#include <server.h>
#include <dblib.h>
#include <caerr.h>
@@ -58,6 +57,7 @@ void event_cancel_reply();
void clear_channel_reply();
void send_err();
void log_header();
void search_fail_reply();
/*
@@ -397,7 +397,7 @@ read_reply(pevext, paddr, hold, pfl)
FAST struct event_ext *pevext;
FAST struct db_addr *paddr;
int hold; /* more on the way if true */
db_field_log *pfl;
void *pfl;
{
FAST struct extmsg *mp = pevext->mp;
FAST struct client *client = pevext->client;
@@ -508,7 +508,6 @@ build_reply(mp, client)
struct db_addr tmp_addr;
FAST struct channel_in_use *pchannel;
void search_fail_reply();
/* Exit quickly if channel not on this node */

View File

@@ -1,26 +1,46 @@
/* The IOC connection request server */
/*
*******************************************************************************
** GTA PROJECT
** Copyright 1988, The Regents of the University of California.
** Los Alamos National Laboratory
** Los Alamos New Mexico 87845
** cast_server.c - GTA request server main loop
** Sun UNIX 4.2 Release 3.4
** First Release- Jeff Hill May 88
**
**
**
** FIXES NEEDED:
**
** Dont send channel found message unless there is memory, a task slot,
** and a TCP socket available. Send a diagnostic instead.
** Or ... make the timeout shorter? This is only a problem if
** they persist in trying to make a connection after getting no
** response.
**
*******************************************************************************
*/
/* @(#)cast_server.c
* $Id$
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 5-88
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .00 joh 030191 Fixed cast server to not block on TCP
* .01 joh 030891 now reuses old client structure
* .02 joh 032091 allways flushes if the client changes and the old
* client has a TCP connection.(bug introduced by .00)
*
* Improvements
* ------------
* Dont send channel found message unless there is memory, a task slot,
* and a TCP socket available. Send a diagnostic instead.
* Or ... make the timeout shorter? This is only a problem if
* they persist in trying to make a connection after getting no
* response.
*/
#include <vxWorks.h>
#include <lstLib.h>
@@ -33,230 +53,288 @@
#include <task_params.h>
#include <server.h>
STATUS
/*
* CAST_SERVER
*
* service UDP messages
*
*/
void
cast_server()
{
struct sockaddr_in sin;
FAST int status;
int i;
FAST struct client *client;
FAST struct client *tmpclient = NULL;
struct sockaddr_in recv_addr;
int recv_addr_size = sizeof(recv_addr);
unsigned nchars;
static struct message_buffer udp_msg;
# define TIMEOUT 60 /* sec */
unsigned long timeout = TIMEOUT * sysClkRateGet();
struct sockaddr_in sin;
FAST int status;
int count;
FAST struct client *client = NULL;
FAST struct client *true_client = NULL;
FAST struct client *temp_client;
struct sockaddr_in recv_addr;
int recv_addr_size = sizeof(recv_addr);
unsigned nchars;
# define TIMEOUT 60 /* sec */
unsigned long timeout = TIMEOUT*sysClkRateGet();
static struct message_buffer udp_msg;
struct client *existing_client();
struct client *create_udp_client();
void rsrv_online_notify_task();
struct client *existing_client();
struct client *create_udp_client();
void rsrv_online_notify_task();
if( IOC_cast_sock!=0 && IOC_cast_sock!=ERROR )
if( (status = close(IOC_cast_sock)) == ERROR )
logMsg("Unable to close open master socket\n");
if( IOC_cast_sock!=0 && IOC_cast_sock!=ERROR )
if( (status = close(IOC_cast_sock)) == ERROR )
logMsg("Unable to close open master socket\n");
/*
* Open the socket.
* Use ARPA Internet address format and datagram socket.
* Format described in <sys/socket.h>.
*/
/*
* Open the socket.
* Use ARPA Internet address format and datagram socket.
* Format described in <sys/socket.h>.
*/
if((IOC_cast_sock = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR){
logMsg("Socket creation error\n");
printErrno (errnoGet ());
taskSuspend(0);
}
if((IOC_cast_sock = socket (AF_INET, SOCK_DGRAM, 0)) == ERROR){
logMsg("Socket creation error\n");
printErrno (errnoGet ());
taskSuspend(0);
}
/* Zero the sock_addr structure */
bfill(&sin, sizeof(sin), 0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = CA_SERVER_PORT;
/* Zero the sock_addr structure */
bfill(&sin, sizeof(sin), 0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = CA_SERVER_PORT;
/* get server's Internet address */
if (bind (IOC_cast_sock, &sin, sizeof (sin)) == ERROR){
logMsg("Bind error\n");
printErrno (errnoGet ());
close (IOC_cast_sock);
taskSuspend(0);
}
/* get server's Internet address */
if( bind(IOC_cast_sock, &sin, sizeof (sin)) == ERROR){
logMsg("Bind error\n");
printErrno (errnoGet ());
close (IOC_cast_sock);
taskSuspend(0);
}
bfill(&udp_msg, sizeof(udp_msg), NULL);
bfill(&udp_msg, sizeof(udp_msg), NULL);
/* tell clients we are on line again */
status = taskSpawn(
CA_ONLINE_NAME,
CA_ONLINE_PRI,
CA_ONLINE_OPT,
CA_ONLINE_STACK,
rsrv_online_notify_task);
if(status<0){
logMsg("Cast_server: couldnt start up online notify task\n");
printErrno(errnoGet ());
}
/* tell clients we are on line again */
status = taskSpawn(
CA_ONLINE_NAME,
CA_ONLINE_PRI,
CA_ONLINE_OPT,
CA_ONLINE_STACK,
rsrv_online_notify_task);
if(status<0){
logMsg("Cast_server: couldnt start up online notify task\n");
printErrno(errnoGet ());
}
while(TRUE){
while(TRUE){
status = recvfrom( IOC_cast_sock,
&udp_msg.cnt,
sizeof(udp_msg.cnt)+sizeof(udp_msg.buf),
/*
* setup new client structure but reuse old structure if
* possible
*
*/
if(!client){
client = create_udp_client(IOC_cast_sock);
if(!client){
taskDelay(sysClkRateGet()*60*5);
continue;
}
}
status = recvfrom(
IOC_cast_sock,
udp_msg.buf,
sizeof(udp_msg.buf),
NULL,
&recv_addr,
&recv_addr_size);
if(status<0){
logMsg("Cast_server: UDP recv error\n");
printErrno(errnoGet ());
taskSuspend(0);
}
if(status<0){
logMsg("Cast_server: UDP recv error\n");
printErrno(errnoGet ());
taskSuspend(0);
}
if(status != udp_msg.cnt){
logMsg("Cast_server: Recieved a corrupt broadcast\n");
continue;
}
udp_msg.cnt = status;
udp_msg.stk = 0;
/*
* If we are talking to a new client flush the old one
* in case it is holding UDP messages for a
* TCP connected client - waiting to see if the
* next message is for this same client.
* (replies to broadcasts are not returned over
* an existing TCP connection to avoid a TCP
* pend which could lock up the cast server).
*/
if( client->valid_addr &&
(client->addr.sin_addr.s_addr !=
recv_addr.sin_addr.s_addr ||
client->addr.sin_port != recv_addr.sin_port)){
cas_send_msg(client, TRUE);
}
client->addr = recv_addr;
client->valid_addr = TRUE;
if(MPDEBUG==2){
logMsg( "cast_server(): msg of %d bytes\n",
status);
logMsg( "from addr %x, port %x \n",
recv_addr.sin_addr,
recv_addr.sin_port);
}
if(MPDEBUG==2){
logMsg( "cast_server(): recieved a broadcast of %d bytes\n", status);
logMsg( "from addr %x, port %x \n",
recv_addr.sin_addr,
recv_addr.sin_port);
}
if(MPDEBUG==3)
count = client->addrq.count;
/* subtract header size */
udp_msg.cnt -= sizeof(udp_msg.cnt);
/*
* check for existing client occurs after
* message process so that this thread never
* blocks sending TCP
*/
status = camessage(client, &udp_msg);
if(status == OK){
if(udp_msg.cnt != udp_msg.stk){
printf( "CA UDP Message OF %d\n",
udp_msg.cnt-udp_msg.stk);
}
}
/* setup new client structure but, reuse old structure if possible */
LOCK_CLIENTQ;
client = existing_client(&recv_addr);
if(!client){
if(tmpclient){
client = tmpclient;
tmpclient = NULL;
}
else
client = create_udp_client(IOC_cast_sock);
if(!client){
UNLOCK_CLIENTQ;
continue;
}
if(client->addrq.count){
LOCK_CLIENTQ;
client->addr = recv_addr;
client->ticks_at_creation = tickGet();
lstAdd(&clientQ, client);
}
true_client = existing_client(&client->addr);
if(true_client == NULL){
client->ticks_at_creation = tickGet();
lstAdd(&clientQ, client);
client = NULL;
}else{
lstConcat(
&true_client->addrq,
&client->addrq);
}
if(MPDEBUG==2)
i = client->addrq.count;
UNLOCK_CLIENTQ;
message_process(client, &udp_msg);
if(MPDEBUG==3){
logMsg( "Fnd %d name matches (%d tot)\n",
client->addrq.count-count,
client->addrq.count);
}
}
/* remove client data structure from list if channel not found */
if(client->addrq.count){
if(MPDEBUG==2)
logMsg( "Found %d new channel name matches (%d cumulative)\n",
client->addrq.count-i,
client->addrq.count);
}
else{
lstDelete(&clientQ, client);
if(!tmpclient)
tmpclient = client;
else
free(client);
}
/*
* allow message to batch up if more are comming
*/
status = ioctl(IOC_cast_sock, FIONREAD, &nchars);
if(status == ERROR){
printErrno(errnoGet(0));
taskSuspend(0);
}
/*
allow message to batch up if more are comming
*/
status = ioctl(IOC_cast_sock, FIONREAD, &nchars);
if(status == ERROR){
printErrno(errnoGet(0));
taskSuspend(0);
}
if(nchars == 0){
client = (struct client *) &clientQ;
while(client = (struct client *) client->node.next)
send_msg(client);
if(nchars == 0){
if(client)
cas_send_msg(client, TRUE);
clean_clientq(timeout);
}
UNLOCK_CLIENTQ;
/*
* catch any that have not been sent yet
*/
LOCK_CLIENTQ;
temp_client = (struct client *) &clientQ;
while(temp_client = (struct client *)
temp_client->node.next){
if(temp_client->proto == IPPROTO_UDP)
cas_send_msg(temp_client, TRUE);
}
}
clean_clientq(timeout);
UNLOCK_CLIENTQ;
}
}
}
struct client
*create_udp_client(sock)
/*
* CREATE_UDP_CLIENT
*
*
*/
struct client *create_udp_client(sock)
unsigned sock;
{
struct client *client;
struct client *client;
client = (struct client *)malloc(sizeof(struct client));
if(!client){
printErrno(errnoGet ());
return NULL;
}
LOCK_CLIENTQ;
client = (struct client *)lstGet(&rsrv_free_clientQ);
UNLOCK_CLIENTQ;
if(MPDEBUG==2)
logMsg( "cast_server(): Creating data structures for new udp client\n");
if(!client){
client = (struct client *)malloc(sizeof(struct client));
if(!client){
logMsg("CA: no mem for another client\n");
printErrno(errnoGet ());
return NULL;
}
}
/*
The following inits to zero done instead of a bfill since
the send and recv buffers are large and don't need initialization.
if(MPDEBUG==3)
logMsg( "cast_server(): Creating new udp client\n");
bfill(client, sizeof(*client), NULL);
*/
lstInit(&client->addrq);
client->tid = 0;
client->send.stk = 0;
client->send.cnt = 0;
client->recv.stk = 0;
client->recv.cnt = 0;
client->evuser = NULL;
client->eventsoff = FALSE;
/*
The following inits to zero done instead of a bfill since
the send and recv buffers are large and don't need initialization.
client->proto = IPPROTO_UDP;
client->send.maxstk = MAX_UDP-sizeof(client->recv.cnt);
FASTLOCKINIT(&client->send.lock);
bfill(client, sizeof(*client), NULL);
*/
lstInit(&client->addrq);
client->tid = 0;
client->send.stk = 0;
client->send.cnt = 0;
client->recv.stk = 0;
client->recv.cnt = 0;
client->evuser = NULL;
client->eventsoff = FALSE;
client->valid_addr = FALSE;
client->disconnect = FALSE; /* for TCP only */
client->recv.maxstk = MAX_UDP;
FASTLOCKINIT(&client->recv.lock);
client->proto = IPPROTO_UDP;
client->send.maxstk = MAX_UDP-sizeof(client->recv.cnt);
FASTLOCKINIT(&client->send.lock);
client->sock = sock;
client->recv.maxstk = MAX_UDP;
FASTLOCKINIT(&client->recv.lock);
return client;
client->sock = sock;
return client;
}
/*
send lock must be applied
*/
udp_to_tcp(client,sock)
* UDP_TO_TCP
*
* send lock must be applied
*
*/
int udp_to_tcp(client,sock)
struct client *client;
unsigned sock;
{
if(MPDEBUG==2)
logMsg("cast_server(): converting udp client to tcp\n");
if(MPDEBUG==3)
logMsg("cast_server(): converting udp client to tcp\n");
client->proto = IPPROTO_TCP;
client->send.maxstk = MAX_TCP;
client->recv.maxstk = MAX_TCP;
client->sock = sock;
client->proto = IPPROTO_TCP;
client->send.maxstk = MAX_TCP;
client->recv.maxstk = MAX_TCP;
client->sock = sock;
return OK;
return OK;
}

View File

@@ -1,17 +1,36 @@
/*
*******************************************************************************
** GTA PROJECT
** Copyright 1988, The Regents of the University of California.
** Los Alamos National Laboratory
** Los Alamos New Mexico 87845
** inmsgtask0.c - GTA request server message reader task.
** Sun UNIX 4.2 Release 3.4
** Bob Dingler February 11, 1988
*******************************************************************************
*/
/* @(#)globalsource.c
* $Id$
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 5-88
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
*/
#define GLBLSOURCE
#include <vxWorks.h>
#include <lstLib.h>
#include <types.h>

View File

@@ -1,11 +1,37 @@
/*
* O N L I N E _ N O T I F Y . C
*
* tell CA clients this a server has joined the network
*
* Author: Jeffrey O. Hill
* @(#)online_notify.c
* $Id$
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 103090
*
* Hisory
* .00 103090 joh First release
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* History
*/
/*
@@ -17,17 +43,13 @@
#include <in.h>
/*
* LAACS includes
* EPICS includes
*/
#include <task_params.h>
#include <iocmsg.h>
#define abort taskSuspend
struct complete_msg{
unsigned length;
struct extmsg extmsg;
};
/*
* RSRV_ONLINE_NOTIFY_TASK
@@ -45,7 +67,7 @@ void rsrv_online_notify_task()
* CA_ONLINE_DELAY [sec] max delay
*/
unsigned long maxdelay = CA_ONLINE_DELAY * sysClkRateGet();
struct complete_msg msg;
struct extmsg msg;
struct sockaddr_in send_addr;
struct sockaddr_in recv_addr;
@@ -90,9 +112,8 @@ void rsrv_online_notify_task()
abort(0);
bfill(&msg, sizeof msg, NULL);
msg.length = htonl(sizeof msg);
msg.extmsg.m_cmmd = htons(IOC_RSRV_IS_UP);
msg.extmsg.m_available = lcl.sin_addr.s_addr;
msg.m_cmmd = htons(IOC_RSRV_IS_UP);
msg.m_available = lcl.sin_addr.s_addr;
/* Zero the sock_addr structure */
bfill(&send_addr, sizeof send_addr, 0);
@@ -101,8 +122,6 @@ void rsrv_online_notify_task()
send_addr.sin_port = htons(CA_CLIENT_PORT);
while(TRUE){
status = sendto(
sock,
&msg,
@@ -120,38 +139,3 @@ void rsrv_online_notify_task()
}
#ifdef JUNKYARD
client = create_udp_client(sock);
client->addr = send_addr;
client->ticks_at_creation = tickGet();
while(TRUE){
reply = (struct extmsg *) ALLOC_MSG(client, 0);
if(!reply)
abort(0);
bfill(reply, sizeof(*reply), NULL);
reply->m_cmmd = IOC_RSRV_IS_UP;
reply->m_available = lcl.sin_addr.s_addr;
reply->m_postsize = 0;
END_MSG(client);
send_msg(client);
taskDelay(delay);
delay = delay << 1;
}
/*
Should it need to quit....
free_one_client(client);
*/
#endif

View File

@@ -1,3 +1,34 @@
/* @(#)rsrv_init.c
* $Id$
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 5-88
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
*/
#include <vxWorks.h>
#include <lstLib.h>
#include <taskLib.h>
@@ -11,35 +42,40 @@
#define DELETE_TASK(TID)\
if(errnoOfTaskGet(TID)!=ERROR)td(TID);
/*
* rsrv_init()
*
*
*
*/
rsrv_init()
{
FAST struct client *client;
void req_server();
void cast_server();
FAST struct client *client;
FASTLOCKINIT(&rsrv_free_addrq_lck);
FASTLOCKINIT(&rsrv_free_eventq_lck);
FASTLOCKINIT(&clientQlock);
FASTLOCKINIT(&rsrv_free_addrq_lck);
FASTLOCKINIT(&rsrv_free_eventq_lck);
FASTLOCKINIT(&clientQlock);
/*
the following is based on the assumtion that external variables
are not reloaded when debugging.
NOTE: NULL below specifies all clients
*/
free_client(NULL);
/*
* the following is based on the assumtion that external variables
* are not reloaded when debugging. NOTE: NULL below specifies all
* clients
*/
free_client(NULL);
DELETE_TASK(taskNameToId(CAST_SRVR_NAME));
DELETE_TASK(taskNameToId(REQ_SRVR_NAME));
taskSpawn( REQ_SRVR_NAME,
REQ_SRVR_PRI,
REQ_SRVR_OPT,
REQ_SRVR_STACK,
req_server);
DELETE_TASK(taskNameToId(CAST_SRVR_NAME));
DELETE_TASK(taskNameToId(REQ_SRVR_NAME));
taskSpawn(REQ_SRVR_NAME,
REQ_SRVR_PRI,
REQ_SRVR_OPT,
REQ_SRVR_STACK,
req_server);
taskSpawn( CAST_SRVR_NAME,
CAST_SRVR_PRI,
CAST_SRVR_OPT,
CAST_SRVR_STACK,
cast_server);
taskSpawn(CAST_SRVR_NAME,
CAST_SRVR_PRI,
CAST_SRVR_OPT,
CAST_SRVR_STACK,
cast_server);
}

View File

@@ -1,12 +1,54 @@
/* @(#)server.h
* $Id$
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 5-88
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 joh 060691 removed 4 byte count from the beginning of
* of each message
* .02 joh 060791 moved send_msg stuff into caserverio.c
*
*/
#ifndef INCLfast_lockh
#include <fast_lock.h>
#endif
#include <iocmsg.h>
#ifndef INCLdb_accessh
#include <db_access.h>
#endif
#ifndef INClstLibh
#include <lstLib.h>
#endif
#ifndef __IOCMSG__
#include <iocmsg.h>
#endif
/* buf & cnt must be contiguous */
/* cnt must be first */
/* buf must be second */
struct message_buffer{
unsigned stk;
@@ -25,9 +67,11 @@ struct client{
struct message_buffer recv;
struct sockaddr_in addr;
void *evuser;
char eventsoff;
unsigned long ticks_at_creation; /* for UDP timeout */
int tid;
char eventsoff;
char valid_addr;
char disconnect; /* disconnect detected */
};
@@ -69,7 +113,8 @@ LOCAL keyed;
GLBLTYPE int IOC_sock;
GLBLTYPE int IOC_cast_sock;
GLBLTYPE LIST clientQ;
GLBLTYPE LIST clientQ; /* locked by clientQlock */
GLBLTYPE LIST rsrv_free_clientQ; /* locked by clientQlock */
GLBLTYPE FAST_LOCK clientQlock;
GLBLTYPE int MPDEBUG;
GLBLTYPE LIST rsrv_free_addrq;
@@ -86,43 +131,25 @@ FASTUNLOCK(&(CLIENT)->send.lock);
#define EXTMSGPTR(CLIENT)\
((struct extmsg *) &(CLIENT)->send.buf[(CLIENT)->send.stk])
#define ALLOC_MSG(CLIENT, EXTSIZE)\
(struct extmsg *)\
((CLIENT)->send.stk + (EXTSIZE) + sizeof(struct extmsg) > \
(CLIENT)->send.maxstk ? send_msg_nolock(CLIENT): NULL,\
(CLIENT)->send.stk + (EXTSIZE) + sizeof(struct extmsg) >\
(CLIENT)->send.maxstk ? NULL : EXTMSGPTR(CLIENT))
/*
* ALLOC_MSG get a ptr to space in the buffer
* END_MSG push a message onto the buffer stack
*
*/
#define ALLOC_MSG(CLIENT, EXTSIZE) cas_alloc_msg(CLIENT, EXTSIZE)
#define END_MSG(CLIENT)\
EXTMSGPTR(CLIENT)->m_postsize = CA_MESSAGE_ALIGN(EXTMSGPTR(CLIENT)->m_postsize),\
(CLIENT)->send.stk += sizeof(struct extmsg) + EXTMSGPTR(CLIENT)->m_postsize
/* send with lock */
#define send_msg(CLIENT)\
{LOCK_SEND(CLIENT); send_msg_nolock(CLIENT); UNLOCK_SEND(CLIENT)};
/* send with empty test */
#define send_msg_nolock(CLIENT)\
!(CLIENT)->send.stk ? FALSE: send_msg_actual(CLIENT)
#define LOCK_CLIENTQ FASTLOCK(&clientQlock)
/* vanilla send */
#define send_msg_actual(CLIENT)\
(\
(CLIENT)->send.cnt = (CLIENT)->send.stk + sizeof((CLIENT)->send.cnt),\
(CLIENT)->send.stk = 0,\
MPDEBUG==2?logMsg("Sent a message of %d bytes\n",(CLIENT)->send.cnt):NULL,\
sendto ( (CLIENT)->sock, \
&(CLIENT)->send.cnt, \
(CLIENT)->send.cnt, \
0,\
&(CLIENT)->addr,\
sizeof((CLIENT)->addr))==ERROR?LOG_SEND_ERROR,FALSE:TRUE\
)
#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock)
#define LOG_SEND_ERROR \
(logMsg("Send_msg() unable to send, connection broken? %\n"))
#define LOCK_CLIENTQ \
FASTLOCK(&clientQlock)
#define UNLOCK_CLIENTQ \
FASTUNLOCK(&clientQlock)
struct client *existing_client();
void camsgtask();
void req_server();
void cast_server();
void cas_send_msg();
struct extmsg *cas_alloc_msg();