Files
epics-base/src/rsrv/server.h
2002-03-14 01:13:58 +00:00

313 lines
7.6 KiB
C

/*
* 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
* .03 joh 071291 moved time stamp from client to the
* channel in use block
* .04 joh 071591 added ticks at last io to the client structure
* .05 joh 103191 moved lock from msg buf to client structure
* .06 joh 050692 added declaration for cac_send_heartbeat()
* .07 joh 022492 added get flag to the event ext block
* .08 joh 090893 added sid field to channel in use block
*
*/
#ifndef INCLserverh
#define INCLserverh
static char *serverhSccsId = "@(#) $Id$";
#if defined(CAS_VERSION_GLOBAL) && 0
# define HDRVERSIONID(NAME,VERS) VERSIONID(NAME,VERS)
#else /*CAS_VERSION_GLOBAL*/
# define HDRVERSIONID(NAME,VERS)
#endif /*CAS_VERSION_GLOBAL*/
#define APIENTRY
#include "epicsAssert.h"
#include <vxLib.h>
#include "ellLib.h"
#include "fast_lock.h"
#include "dbDefs.h"
#include "db_access.h"
#include "dbEvent.h"
#include "caProto.h"
#include "bucketLib.h"
#include "taskwd.h"
#include "asLib.h"
#include "asDbLib.h"
#include <socket.h>
#include "addrList.h"
#include "net_convert.h"
/*
* !! buf must be the first item in this structure !!
* This guarantees that buf will have 8 byte natural
* alignment
*
* Conversions:
* The contents of message_buffer has to be converted
* from network to host format and vice versa.
* For efficiency reasons, the caHdr structure that's common
* to all messages is converted only once:
* 1) from net to host just after receiving it in camessage()
* 2) from host to net in cas_send_msg()
*
* The remaining message_buffer content, however, is always
* in net format!
*
* The terminating unsigned long pad0 field is there to force the
* length of the message_buffer to be a multiple of 8 bytes.
* This is due to the sequential placing of two message_buffer
* structures (trans, rec) within the client structure.
* Eight-byte alignment is required by the Sparc 5 and other RISC
* processors.
*
* CAVEAT: This assumes the following:
* o an array of MAX_MSG_SIZE chars takes a multiple of 8 bytes.
* o four unsigned longs also take up a multiple of 8 bytes
* (usually 2).
* NOTE:
* o we should solve the above message alignment problems by
* allocating the message buffers
*
*/
struct message_buffer{
char buf[MAX_MSG_SIZE];
unsigned long stk;
unsigned long maxstk;
unsigned long cnt;
unsigned long pad0; /* force 8 byte alignement */
};
struct client{
ELLNODE node;
struct message_buffer send;
struct message_buffer recv;
FAST_LOCK lock;
FAST_LOCK putNotifyLock;
FAST_LOCK addrqLock;
FAST_LOCK eventqLock;
ELLLIST addrq;
ELLLIST putNotifyQue;
struct sockaddr_in addr;
unsigned long ticks_at_last_send;
unsigned long ticks_at_last_recv;
void *evuser;
char *pUserName;
char *pHostName;
SEM_ID blockSem; /* used whenever the client blocks */
int sock;
int proto;
int tid;
unsigned minor_version_number;
unsigned udpNoBuffCount;
char disconnect; /* disconnect detected */
};
/*
* for tracking db put notifies
*/
typedef struct rsrv_put_notify{
ELLNODE node;
PUTNOTIFY dbPutNotify;
caHdr msg;
unsigned long valueSize; /* size of block pointed to by dbPutNotify */
char busy; /* put notify in progress */
char onExtraLaborQueue;
}RSRVPUTNOTIFY;
/*
* per channel structure
* (stored in addrq off of a client block)
*/
struct channel_in_use{
ELLNODE node;
ELLLIST eventq;
struct client *client;
RSRVPUTNOTIFY *pPutNotify; /* potential active put notify */
const unsigned cid; /* client id */
const unsigned sid; /* server id */
unsigned long ticks_at_creation; /* for UDP timeout */
struct dbAddr addr;
ASCLIENTPVT asClientPVT;
};
/*
* Event block extension for channel access
* some things duplicated for speed
*/
struct event_ext{
ELLNODE node;
caHdr msg;
struct channel_in_use *pciu;
struct event_block *pdbev; /* ptr to db event block */
unsigned size; /* for speed */
unsigned mask;
char modified; /* mod & ev flw ctrl enbl */
char send_lock; /* lock send buffer */
};
/* NOTE: external used so they remember the state across loads */
#ifdef GLBLSOURCE
# define GLBLTYPE
# define GLBLTYPE_INIT(A)
#else
# define GLBLTYPE extern
# define GLBLTYPE_INIT(A)
#endif
/*
* for debug-level dependent messages:
*/
#ifdef DEBUG
# define DLOG(level, fmt, a1, a2, a3, a4, a5, a6) \
if (CASDEBUG > level) \
logMsg (fmt, a1, a2, a3, a4, a5, a6)
# define DBLOCK(level, code) \
if (CASDEBUG > level) \
{ \
code; \
}
#else
# define DLOG(level, fmt, a1, a2, a3, a4, a5, a6)
# define DBLOCK(level, code)
#endif
GLBLTYPE int CASDEBUG;
GLBLTYPE int IOC_sock;
GLBLTYPE int IOC_cast_sock;
GLBLTYPE unsigned short ca_server_port;
GLBLTYPE ELLLIST clientQ; /* locked by clientQlock */
GLBLTYPE ELLLIST beaconAddrList;
GLBLTYPE FAST_LOCK clientQlock;
GLBLTYPE struct client *prsrv_cast_client;
GLBLTYPE BUCKET *pCaBucket;
GLBLTYPE void *rsrvClientFreeList;
GLBLTYPE void *rsrvChanFreeList;
GLBLTYPE void *rsrvEventFreeList;
#define CAS_HASH_TABLE_SIZE 4096
/*
* set true if max memory block drops below MAX_BLOCK_THRESHOLD
*/
#define MAX_BLOCK_THRESHOLD 100000
GLBLTYPE int casBelowMaxBlockThresh;
#define SEND_LOCK(CLIENT)\
{\
FASTLOCK(&(CLIENT)->lock);\
}
#define SEND_UNLOCK(CLIENT)\
{ \
FASTUNLOCK(&(CLIENT)->lock);\
}
#define EXTMSGPTR(CLIENT)\
((caHdr *) &(CLIENT)->send.buf[(CLIENT)->send.stk])
/*
* 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(caHdr) + EXTMSGPTR(CLIENT)->m_postsize
#define LOCK_CLIENTQ FASTLOCK(&clientQlock);
#define UNLOCK_CLIENTQ FASTUNLOCK(&clientQlock);
struct client *existing_client();
int camsgtask();
void cas_send_msg();
caHdr *cas_alloc_msg();
int rsrv_online_notify_task();
void cac_send_heartbeat();
int client_stat(unsigned level);
void casr(unsigned level);
int req_server(void);
int cast_server(void);
int free_client(struct client *client);
struct client *create_udp_client(unsigned sock);
int udp_to_tcp(struct client *client, unsigned sock);
int camessage(
struct client *client,
struct message_buffer *recv
);
void cas_send_heartbeat(
struct client *pc
);
void write_notify_reply(void *pArg);
int rsrvCheckPut (const struct channel_in_use *pciu);
/*
* !!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*/
#define S_db_Pending (M_dbAccess|37) /*Request is pending*/
#endif /*INCLserverh*/