Compare commits

..

15 Commits

Author SHA1 Message Date
Janet B. Anderson
25a6340993 Added filio.h include for solaris build. 1995-11-13 16:55:03 +00:00
Jeff Hill
a3652fd54e improvents for better client reconnect 1995-11-08 23:48:26 +00:00
Jeff Hill
107ae2cee8 fixed log client reconnect problems 1995-11-08 23:46:27 +00:00
Jeff Hill
deb5e9c973 add log entries 1995-11-08 23:45:10 +00:00
Jeff Hill
196f2302a4 changes associated with fixing the log client 1995-11-08 23:44:41 +00:00
Jeff Hill
2a21b01b0e fixed bug occuring when diagnostic is printed and the env var cant be found 1995-11-08 23:43:51 +00:00
Jeff Hill
56465da07f log entries changed 1995-11-08 23:38:41 +00:00
Jeff Hill
ee9457970a changes froim chris T 1995-11-08 23:36:31 +00:00
Jeff Hill
89a3746869 changes from Chris T 1995-11-08 23:20:56 +00:00
Janet B. Anderson
5be8f4999d Removed "-s" compile option 1995-11-08 19:28:51 +00:00
Marty Kraimer
b278c803ce When calling db_post_event for argument fields ass DBE_LOG 1995-11-08 15:01:36 +00:00
Jeff Hill
50b8361078 more changes from Chris Timossi 1995-10-25 16:46:01 +00:00
Jeff Hill
2a121a4276 changes from Chris Timossi 1995-10-24 21:21:31 +00:00
Jeff Hill
7b03ab0182 Changes to avoid spurious ECONREFUSED returned from recvfrom() under linux 1995-10-22 22:27:47 +00:00
cvs2svn
73a224a6ce This commit was manufactured by cvs2svn to create tag 'R3.12.1.4'. 1995-10-20 20:21:33 +00:00
12 changed files with 606 additions and 178 deletions

View File

@@ -1,4 +1,5 @@
/************************************************************************/
/* $Id$ */
/* */
/* L O S A L A M O S */
/* Los Alamos National Laboratory */
@@ -45,6 +46,7 @@
/* 021794 joh turn on SO_REUSEADDR only after the test for */
/* address in use so that test works on UNIX */
/* kernels that support multicast */
/* $Log$ */
/* */
/*_begin */
/************************************************************************/
@@ -1044,6 +1046,16 @@ LOCAL void udp_recv_msg(struct ioc_in_use *piiu)
UNLOCK;
return;
}
# ifdef linux
/*
* Avoid spurious ECONNREFUSED bug
* in linux
*/
if (MYERRNO==ECONNREFUSED) {
UNLOCK;
return;
}
# endif
ca_printf("Unexpected UDP failure %s\n", strerror(MYERRNO));
}
else if(status > 0){

View File

@@ -1,4 +1,6 @@
/*
* $Id$
*
* REPEATER.C
*
* CA broadcast repeater
@@ -59,6 +61,8 @@
* .08 102993 joh toggle set sock opt to set
* .09 070195 joh discover client has vanished by connecting its
* datagram socket (and watching for ECONNREFUSED)
*
* $Log$
*/
static char *sccsId = "@(#)$Id$";
@@ -149,6 +153,15 @@ void ca_repeater()
&from_size);
if(size < 0){
# ifdef linux
/*
* Avoid spurious ECONNREFUSED bug
* in linux
*/
if (MYERRNO==ECONNREFUSED) {
continue;
}
# endif
ca_printf("CA Repeater: recv err %s\n",
strerror(MYERRNO));
continue;

View File

@@ -13,6 +13,7 @@
*
* 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)
@@ -26,17 +27,18 @@
* Advanced Photon Source
* Argonne National Laboratory
*
* Lawrence Berkley National Laboratory
* Lawrence Berkley National Laboratory
*
* Modification Log:
* -----------------
*
*/
/*
* Windows includes
*/
#include <windows.h>
#include <process.h>
#include <mmsystem.h>
#include "iocinf.h"
@@ -44,6 +46,10 @@
#error This source is specific to WIN32
#endif
long offset_time; /* time diff (sec) between 1970 and when windows started */
DWORD prev_time;
static void init_timers();
static int get_subnet_mask ( char SubNetMaskStr[256]);
static int RegTcpParams (char IpAddr[256], char SubNetMask[256]);
static int RegKeyData (CHAR *RegPath, HANDLE hKeyRoot, LPSTR lpzValueName,
@@ -55,11 +61,25 @@ static int RegKeyData (CHAR *RegPath, HANDLE hKeyRoot, LPSTR lpzValueName,
*/
void cac_gettimeval(struct timeval *pt)
{
SYSTEMTIME st;
/**
The multi-media timers used here should be good to a millisecond
resolution. However, since the timer rolls back to 0 every 49.7
days (2^32 ms, 4,294,967.296 sec), it's not very good for
time stamping over long periods (if Windows is restarted more
often than 49 days, it wont be a problem). An attempt is made
to keep the time returned increasing, but there is no guarantee
the UTC time is right after 49 days.
**/
GetSystemTime(&st);
pt->tv_sec = time(NULL);
pt->tv_usec = st.wMilliseconds*1000;
DWORD win_sys_time; /* time (ms) since windows started */
win_sys_time = timeGetTime();
if (prev_time > win_sys_time) { /* must have been a timer roll-over */
offset_time += 4294967; /* add number of seconds in 49.7 days */
}
pt->tv_sec = (long)win_sys_time/1000 + offset_time; /* time (sec) since 1970 */
pt->tv_usec = (long)((win_sys_time % 1000) * 1000);
prev_time = win_sys_time;
}
@@ -102,8 +122,7 @@ void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
*/
int cac_os_depen_init(struct ca_static *pcas)
{
int status;
WSADATA WsaData;
int status;
ca_static = pcas;
@@ -117,10 +136,7 @@ int cac_os_depen_init(struct ca_static *pcas)
/* signal(SIGPIPE,SIG_IGN); */
# ifdef _WINSOCKAPI_
status = WSAStartup(MAKEWORD(1,1), &WsaData);
assert (status==0);
# endif
/* DllMain does most OS dependent init & cleanup */
status = ca_os_independent_init ();
@@ -414,7 +430,6 @@ static int RegKeyData (CHAR *RegPath, HANDLE hKeyRoot, LPSTR lpzValueName,
retCode = RegQueryValueEx (hKey, // Key handle returned from
RegOpenKeyEx.
lpzValueName, // Name of value.
NULL, // Reserved, dword = NULL.
lpdwType, // Type of data.
@@ -435,37 +450,56 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
int status;
WSADATA WsaData;
TIMECAPS tc;
UINT wTimerRes;
switch (dwReason) {
case DLL_PROCESS_ATTACH:
if ((status = WSAStartup(MAKEWORD(1,1), &WsaData)) != 0)
return FALSE;
#if _DEBUG
#if _DEBUG /* for gui applications, setup console for error messages */
if (AllocConsole()) {
SetConsoleTitle("Channel Access Status");
freopen( "CONOUT$", "a", stderr );
fprintf(stderr, "Process attached to ca.dll R12\n");
}
#endif
fprintf(stderr, "Process attached to ca.dll R3.12.1\n");
#endif /* init. winsock */
if ((status = WSAStartup(MAKEWORD(1,1), &WsaData)) != 0) {
fprintf(stderr,"Cant init winsock \n");
return FALSE;
}
/* setup multi-media timer */
if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
fprintf(stderr,"cant get timer info \n");
return FALSE;
}
/* set for 1 ms resoulution */
wTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
status = timeBeginPeriod(wTimerRes);
if (status != TIMERR_NOERROR)
fprintf(stderr,"timer setup failed\n");
offset_time = (long)time(NULL) - (long)timeGetTime()/1000;
prev_time = timeGetTime();
break;
case DLL_PROCESS_DETACH:
timeEndPeriod(wTimerRes);
if ((status = WSACleanup()) !=0)
return FALSE;
break;
case DLL_THREAD_ATTACH:
#if _DEBUG
fprintf(stderr, "Thread attached to ca.dll R12\n");
fprintf(stderr, "Thread attached to ca.dll R3.12.1\n");
#endif
break;
case DLL_THREAD_DETACH:
#if _DEBUG
fprintf(stderr, "Thread detached from ca.dll R12\n");
fprintf(stderr, "Thread detached from ca.dll R3.12.1\n");
#endif
break;
@@ -475,6 +509,8 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
return TRUE;
}

View File

@@ -32,6 +32,8 @@
* vars under vxWorks
* .05 04-20-95 anj changes to use CONFIG_ENV
* .06 05-24-95 joh added return stmnt to epicsPrtEnvParams()
* .07 11-03-96 joh fixed bug occuring when diagnostic is
* printed and the env var cant be found
*
* make options
* -DvxWorks makes a version for VxWorks
@@ -195,8 +197,9 @@ double *pDouble; /* O pointer to place to store value */
if (count == 1) {
return 0;
}
(void)printf("Unable to find a real number in %s=%s\n",
pParam->name, text);
}
(void)printf("illegal value for %s:%s\n", pParam->name, text);
return -1;
}
@@ -250,8 +253,9 @@ struct in_addr *pAddr; /* O pointer to struct to receive inet addr */
pAddr->s_addr = status;
return 0;
}
(void)printf("Unable to find an IP address in %s=%s\n",
pParam->name, text);
}
(void)printf("illegal value for %s:%s\n", pParam->name, text);
return -1;
}
@@ -303,8 +307,9 @@ long *pLong; /* O pointer to place to store value */
count = sscanf(text, "%ld", pLong);
if (count == 1)
return 0;
(void)printf("Unable to find an integer in %s=%s\n",
pParam->name, text);
}
(void)printf("illegal value for %s:%s\n", pParam->name, text);
return -1;
}

View File

@@ -32,6 +32,8 @@
* vars under vxWorks
* .05 04-20-95 anj changes to use CONFIG_ENV
* .06 05-24-95 joh added return stmnt to epicsPrtEnvParams()
* .07 11-03-96 joh fixed bug occuring when diagnostic is
* printed and the env var cant be found
*
* make options
* -DvxWorks makes a version for VxWorks
@@ -195,8 +197,9 @@ double *pDouble; /* O pointer to place to store value */
if (count == 1) {
return 0;
}
(void)printf("Unable to find a real number in %s=%s\n",
pParam->name, text);
}
(void)printf("illegal value for %s:%s\n", pParam->name, text);
return -1;
}
@@ -250,8 +253,9 @@ struct in_addr *pAddr; /* O pointer to struct to receive inet addr */
pAddr->s_addr = status;
return 0;
}
(void)printf("Unable to find an IP address in %s=%s\n",
pParam->name, text);
}
(void)printf("illegal value for %s:%s\n", pParam->name, text);
return -1;
}
@@ -303,8 +307,9 @@ long *pLong; /* O pointer to place to store value */
count = sscanf(text, "%ld", pLong);
if (count == 1)
return 0;
(void)printf("Unable to find an integer in %s=%s\n",
pParam->name, text);
}
(void)printf("illegal value for %s:%s\n", pParam->name, text);
return -1;
}

View File

@@ -27,6 +27,7 @@
* Modification Log: errPrintfVX.c
* -----------------
* .01 02-16-95 mrk Extracted from errSymLib.c
* $Log$
***************************************************************************
*/
@@ -59,8 +60,6 @@
static int mprintf (const char *pFormat, ...);
static int vmprintf (const char *pFormat, va_list pvar);
extern FILE *iocLogFile;
LOCAL SEM_ID clientWaitForTask;
LOCAL SEM_ID clientWaitForCompletion;
LOCAL SEM_ID serverWaitForWork;
@@ -263,8 +262,7 @@ LOCAL int vmprintf (const char *pFormat, va_list pvar)
s0 = vfprintf(stdout,pFormat,pvar);
fflush(stdout);
s1 = vfprintf(iocLogFile,pFormat,pvar);
fflush(iocLogFile);
s1 = iocLogVPrintf(pFormat,pvar);
va_end(pvar);
if (s1<0) {
return s1;

View File

@@ -70,6 +70,7 @@
* routines in a backwards compatible way so that
* we eliminate delete ambiguity (chance of the same
* being reused).
* $Log$
*
* NOTES:
*

View File

@@ -1,5 +1,4 @@
/* $Id$
* archive logMsg() from several IOC's to a common rotating file
*
*
* Author: Jeffrey O. Hill
@@ -33,64 +32,114 @@
* .00 joh 080791 Created
* .01 joh 081591 Added epics env config
* .02 joh 011995 Allow stdio also
* $Log$
*/
#include <string.h>
#include <stdio.h>
#include <vxWorks.h>
#include <ioLib.h>
#include <taskLib.h>
#include <errno.h>
#include <assert.h>
#include <socket.h>
#include <in.h>
#include <inetLib.h>
#include <errnoLib.h>
#include <ioLib.h>
#include <taskLib.h>
#include <logLib.h>
#include <inetLib.h>
#include <sockLib.h>
#include <sysLib.h>
#include <semLib.h>
#include <rebootLib.h>
#include <epicsPrint.h>
#include <envDefs.h>
#include <task_params.h>
LOCAL FILE *iocLogFile = NULL;
LOCAL int iocLogFD = ERROR;
LOCAL int iocLogDisable = 0;
LOCAL unsigned iocLogTries = 0U;
LOCAL unsigned iocLogConnectCount = 0U;
FILE *iocLogFile = NULL;
int iocLogFD = ERROR;
int iocLogDisable;
LOCAL long ioc_log_port;
LOCAL struct in_addr ioc_log_addr;
static long ioc_log_port;
static struct in_addr ioc_log_addr;
int iocLogInit(void);
LOCAL int getConfig(void);
LOCAL void failureNotify(ENV_PARAM *pparam);
LOCAL void logClientShutdown(void);
LOCAL void logRestart(void);
LOCAL int iocLogAttach(void);
LOCAL void logClientRollLocalPort(void);
int iocLogInit();
static int getConfig();
static void failureNoptify();
LOCAL SEM_ID iocLogMutex; /* protects stdio */
LOCAL SEM_ID iocLogSignal; /* reattach to log server */
/*
*
* iocLogInit()
*
*
*/
int
iocLogInit()
int iocLogInit(void)
{
int sock;
struct sockaddr_in addr;
int status;
int status;
int attachStatus;
int options;
if(iocLogDisable){
return OK;
}
options = SEM_Q_PRIORITY|SEM_DELETE_SAFE|SEM_INVERSION_SAFE;
iocLogMutex = semMCreate(options);
if(!iocLogMutex){
return ERROR;
}
iocLogSignal = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
if(!iocLogSignal){
return ERROR;
}
attachStatus = iocLogAttach();
status = rebootHookAdd((FUNCPTR)logClientShutdown);
if (status<0) {
epicsPrintf("Unable to add log server reboot hook\n");
}
status = taskSpawn(
LOG_RESTART_NAME,
LOG_RESTART_PRI,
LOG_RESTART_OPT,
LOG_RESTART_STACK,
(FUNCPTR)logRestart,
0,0,0,0,0,0,0,0,0,0);
if (status<0) {
epicsPrintf("Unable to start log server connection watch dog\n");
}
return attachStatus;
}
/*
* iocLogAttach()
*/
int iocLogAttach(void)
{
int sock;
struct sockaddr_in addr;
int status;
int optval;
FILE *fp;
status = getConfig();
if(status<0){
logMsg (
"iocLogClient: EPICS environment under specified\n",
0,0,0,0,0,0);
logMsg (
"iocLogClient: failed to initialize\n",
0,0,0,0,0,0);
epicsPrintf (
"iocLogClient: EPICS environment under specified\n");
epicsPrintf ("iocLogClient: failed to initialize\n");
return ERROR;
}
@@ -99,9 +148,8 @@ iocLogInit()
SOCK_STREAM, /* type */
0); /* deflt proto */
if (sock < 0){
logMsg( "iocLogClient: no socket errno %d\n",
errnoGet(),
0,0,0,0,0);
epicsPrintf ("iocLogClient: no socket error %s\n",
strerror(errno));
return ERROR;
}
@@ -111,7 +159,7 @@ iocLogInit()
/* set the port */
addr.sin_port = htons(ioc_log_port);
/* set the port */
/* set the addr */
addr.sin_addr.s_addr = ioc_log_addr.s_addr;
/* connect */
@@ -123,25 +171,213 @@ iocLogInit()
char name[INET_ADDR_LEN];
inet_ntoa_b(addr.sin_addr, name);
logMsg(
if (iocLogTries==0U) {
epicsPrintf(
"iocLogClient: unable to connect to %s port %d because \"%s\"\n",
(int) name,
addr.sin_port,
(int) strerror(errnoGet()),
0,0,0);
name,
addr.sin_port,
strerror(errno));
}
iocLogTries++;
close(sock);
return ERROR;
}
logFdAdd (sock);
iocLogTries=0U;
iocLogConnectCount++;
iocLogFile = fdopen (sock, "a");
/*
* discover that the connection has expired
* (after a long delay)
*/
optval = TRUE;
status = setsockopt( sock,
SOL_SOCKET,
SO_KEEPALIVE,
(char *) &optval,
sizeof(optval));
if(status<0){
epicsPrintf ("iocLogClient: %s\n", strerror(errno));
close(sock);
return ERROR;
}
/*
* set how long we will wait for the TCP state machine
* to clean up when we issue a close(). This
* guarantees that messages are serialized when we
* switch connections.
*/
{
struct linger lingerval;
lingerval.l_onoff = TRUE;
lingerval.l_linger = 60*5;
status = setsockopt( sock,
SOL_SOCKET,
SO_LINGER,
(char *) &lingerval,
sizeof(lingerval));
if(status<0){
epicsPrintf ("iocLogClient: %s\n", strerror(errno));
close(sock);
return ERROR;
}
}
fp = fdopen (sock, "a");
/*
* mutex on
*/
status = semTake(iocLogMutex, WAIT_FOREVER);
assert(status==OK);
/*
* close any preexisting connection to the log server
*/
if (iocLogFile) {
logFdDelete(iocLogFD);
fclose(iocLogFile);
iocLogFile = NULL;
iocLogFD = ERROR;
}
else if (iocLogFD!=ERROR) {
logFdDelete(iocLogFD);
close(iocLogFD);
iocLogFD = ERROR;
}
/*
* export the new connection
*/
iocLogFD = sock;
logFdAdd (iocLogFD);
iocLogFile = fp;
/*
* mutex off
*/
status = semGive(iocLogMutex);
assert(status==OK);
return OK;
}
/*
* logRestart()
*/
LOCAL void logRestart(void)
{
int status;
int reattach;
int delay = LOG_RESTART_DELAY;
/*
* roll the local port forward so that we dont collide
* with the first port assigned when we reboot
*/
logClientRollLocalPort();
while (1) {
semTake(iocLogSignal, delay);
/*
* mutex on
*/
status = semTake(iocLogMutex, WAIT_FOREVER);
assert(status==OK);
if (iocLogFile==NULL) {
reattach = TRUE;
}
else {
reattach = ferror(iocLogFile);
}
/*
* mutex off
*/
status = semGive(iocLogMutex);
assert(status==OK);
if (reattach==FALSE) {
continue;
}
/*
* restart log server
*/
iocLogConnectCount = 0U;
logClientRollLocalPort();
}
}
/*
* logClientRollLocalPort()
*/
LOCAL void logClientRollLocalPort(void)
{
int status;
/*
* roll the local port forward so that we dont collide
* with it when we reboot
*/
while (iocLogConnectCount<10U) {
/*
* switch to a new log server connection
*/
status = iocLogAttach();
if (status==OK) {
/*
* only print a message after the first connect
*/
if (iocLogConnectCount==1U) {
printf(
"iocLogClient: reconnected to the log server\n");
}
}
else {
/*
* if we cant connect then we will roll
* the port later when we can
* (we must not spin on connect fail)
*/
if (errno!=ETIMEDOUT) {
return;
}
}
}
}
/*
* logClientShutdown()
*/
LOCAL void logClientShutdown(void)
{
if (iocLogFD!=ERROR) {
/*
* unfortunately this does not currently work because WRS
* runs the reboot hooks in the order the order that
* they are installed (and the network is already shutdown
* by the time we get here)
*/
#if 0
/*
* this aborts the connection because we
* have specified a nill linger interval
*/
printf("log client: lingering for connection close...");
close(iocLogFD);
printf("done\n");
#endif
}
}
/*
@@ -151,8 +387,7 @@ iocLogInit()
*
*
*/
static int
getConfig()
LOCAL int getConfig(void)
{
long status;
@@ -160,7 +395,7 @@ getConfig()
&EPICS_IOC_LOG_PORT,
&ioc_log_port);
if(status<0){
failureNoptify(&EPICS_IOC_LOG_PORT);
failureNotify(&EPICS_IOC_LOG_PORT);
return ERROR;
}
@@ -168,7 +403,7 @@ getConfig()
&EPICS_IOC_LOG_INET,
&ioc_log_addr);
if(status<0){
failureNoptify(&EPICS_IOC_LOG_INET);
failureNotify(&EPICS_IOC_LOG_INET);
return ERROR;
}
@@ -178,42 +413,59 @@ getConfig()
/*
*
* failureNotify()
*
*
*/
static void
failureNoptify(pparam)
ENV_PARAM *pparam;
LOCAL void failureNotify(ENV_PARAM *pparam)
{
logMsg( "IocLogClient: EPICS environment variable \"%s\" undefined\n",
(int) pparam->name,
0,0,0,0,0);
epicsPrintf(
"IocLogClient: EPICS environment variable \"%s\" undefined\n",
pparam->name);
}
/*
*
* unused
*
*
* iocLogVPrintf()
*/
#ifdef JUNKYARD
ioTaskStdSet(taskIdSelf(), 1, sock);
int iocLogVPrintf(const char *pFormat, va_list pvar)
{
int status;
int semStatus;
while (1) {
date();
/*
memShow(0);
i(0);
checkStack(0);
*/
/*
* 60 min
*/
taskDelay(sysClkRateGet() * 60 * 60);
if (!pFormat || iocLogDisable) {
return 0;
}
#endif
/*
* mutex on
*/
semStatus = semTake(iocLogMutex, WAIT_FOREVER);
assert(semStatus==OK);
if (iocLogFile) {
status = vfprintf(iocLogFile, pFormat, pvar);
if (status>0) {
status = fflush(iocLogFile);
}
if (status<0) {
logFdDelete(iocLogFD);
fclose(iocLogFile);
iocLogFile = NULL;
iocLogFD = ERROR;
semStatus = semGive(iocLogSignal);
assert(semStatus==OK);
}
}
else {
status = EOF;
}
/*
* mutex off
*/
semStatus = semGive(iocLogMutex);
assert(semStatus==OK);
return status;
}

View File

@@ -406,7 +406,7 @@ static void monitor(pcalc)
/* check all input fields for changes*/
for(i=0, pnew=&pcalc->a, pprev=&pcalc->la; i<ARG_MAX; i++, pnew++, pprev++) {
if((*pnew != *pprev) || (monitor_mask&DBE_ALARM)) {
db_post_events(pcalc,pnew,monitor_mask|DBE_VALUE);
db_post_events(pcalc,pnew,monitor_mask|DBE_VALUE|DBE_LOG);
*pprev = *pnew;
}
}

View File

@@ -389,7 +389,7 @@ static void monitor(psub)
/* check all input fields for changes*/
for(i=0, pnew=&psub->a, pprev=&psub->la; i<ARG_MAX; i++, pnew++, pprev++) {
if(*pnew != *pprev) {
db_post_events(psub,pnew,monitor_mask|DBE_VALUE);
db_post_events(psub,pnew,monitor_mask|DBE_VALUE|DBE_LOG);
*pprev = *pnew;
}
}

View File

@@ -2,7 +2,7 @@ EPICS = ../../../..
include Target.include
include $(EPICS)/config/CONFIG_BASE
USR_LDLIBS = -lca -lCom -lm -s
USR_LDLIBS = -lca -lCom -lm
DEPLIBS = $(EPICS_BASE_LIB)/libca.a $(EPICS_BASE_LIB)/libCom.a
SRCS.c = \

View File

@@ -46,6 +46,10 @@
* .08 092292 joh improved message sent to the log
* .09 050494 pg HPUX port changes.
* .10 021694 joh ANSI C
* $Log$
* Revision 1.16 1995/11/08 23:48:26 jhill
* improvents for better client reconnect
*
*/
static char *pSCCSID = "@(#)iocLogServer.c 1.9\t05/05/94";
@@ -54,21 +58,27 @@ static char *pSCCSID = "@(#)iocLogServer.c 1.9\t05/05/94";
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netdb.h>
# ifdef SOLARIS
# include <sys/filio.h>
# endif
#include <bsdProto.h>
#include <envDefs.h>
#include <fdmgr.h>
static long ioc_log_port;
static unsigned short ioc_log_port;
static long ioc_log_file_limit;
static char ioc_log_file_name[64];
@@ -113,6 +123,7 @@ static int getConfig(void);
static int openLogFile(struct ioc_log_server *pserver);
static void handleLogFileError(void);
static void envFailureNotify(ENV_PARAM *pparam);
static void freeLogClient(struct iocLogClient *pclient);
/*
@@ -126,7 +137,7 @@ int main()
struct timeval timeout;
int status;
struct ioc_log_server *pserver;
int optval=1;
int optval;
status = getConfig();
if(status<0){
@@ -158,6 +169,7 @@ int main()
return ERROR;
}
optval = TRUE;
status = setsockopt( pserver->sock,
SOL_SOCKET,
SO_REUSEADDR,
@@ -179,8 +191,8 @@ int main()
sizeof (serverAddr) );
if (status<0) {
fprintf(stderr,
"ioc log server allready installed on port %ld?\n",
ioc_log_port);
"iocLogServer: a server is already installed on port %u?\n",
(unsigned)ioc_log_port);
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
return ERROR;
}
@@ -192,6 +204,20 @@ int main()
return ERROR;
}
/*
* Set non blocking IO
* to prevent dead locks
*/
optval = TRUE;
status = ioctl(
pserver->sock,
FIONBIO,
&optval);
if(status<0){
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
return ERROR;
}
status = openLogFile(pserver);
if(status<0){
fprintf(stderr,
@@ -201,10 +227,11 @@ int main()
return ERROR;
}
status = fdmgr_add_fd(
status = fdmgr_add_callback(
pserver->pfdctx,
pserver->sock,
acceptNewClient,
fdi_read,
acceptNewClient,
pserver);
if(status<0){
return ERROR;
@@ -268,7 +295,7 @@ static void acceptNewClient(void *pParam)
struct sockaddr_in addr;
char *pname;
int status;
int optval;
pclient = (struct iocLogClient *)
malloc(sizeof *pclient);
@@ -279,10 +306,28 @@ static void acceptNewClient(void *pParam)
pclient->insock = accept(pserver->sock, NULL, 0);
if(pclient->insock<0){
free(pclient);
fprintf(stderr, "Accept Error %d\n", errno);
if (errno!=EWOULDBLOCK) {
fprintf(stderr, "Accept Error %d\n", errno);
}
return;
}
/*
* Set non blocking IO
* to prevent dead locks
*/
optval = TRUE;
status = ioctl(
pclient->insock,
FIONBIO,
&optval);
if(status<0){
close(pclient->insock);
free(pclient);
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, strerror(errno));
return;
}
pclient->pserver = pserver;
pclient->need_prefix = TRUE;
pclient->ptopofstack = pclient->recvbuf;
@@ -313,6 +358,7 @@ static void acceptNewClient(void *pParam)
logTime(pclient);
#if 0
status = fprintf(
pclient->pserver->poutfile,
"%s %s ----- Client Connect -----\n",
@@ -321,6 +367,7 @@ static void acceptNewClient(void *pParam)
if(status<0){
handleLogFileError();
}
#endif
/*
* turn on KEEPALIVE so if the client crashes
@@ -340,11 +387,29 @@ static void acceptNewClient(void *pParam)
}
}
fdmgr_add_fd(
pserver->pfdctx,
pclient->insock,
readFromClient,
pclient);
# define SOCKET_SHUTDOWN_WRITE_SIDE 1
status = shutdown(pclient->insock, SOCKET_SHUTDOWN_WRITE_SIDE);
if(status<0){
close(pclient->insock);
free(pclient);
printf("%s:%d %s\n", __FILE__, __LINE__,
strerror(errno));
return;
}
status = fdmgr_add_callback(
pserver->pfdctx,
pclient->insock,
fdi_read,
readFromClient,
pclient);
if (status<0) {
close(pclient->insock);
free(pclient);
fprintf(stderr, "%s:%d client fdmgr_add_callback() failed\n",
__FILE__, __LINE__);
return;
}
}
@@ -362,66 +427,36 @@ static void readFromClient(void *pParam)
int length;
char *pcr;
char *pline;
unsigned stacksize;
int stacksize;
int size;
logTime(pclient);
stacksize = pclient->ptopofstack - pclient->recvbuf;
length = read(pclient->insock,
size = sizeof(pclient->recvbuf)-stacksize-1;
assert(size>0);
length = recv(pclient->insock,
pclient->ptopofstack,
sizeof(pclient->recvbuf)-stacksize-1);
size,
0);
if (length <= 0) {
# ifdef DEBUG
if(length == 0){
fprintf(stderr, "iocLogServer: nil message disconnect\n");
}
# endif
/*
* flush any leftovers
*/
if(stacksize){
status = fprintf(
pclient->pserver->poutfile,
"%s %s ",
pclient->name,
pclient->ascii_time);
if(status<0){
handleLogFileError();
}
status = fwrite(
pclient->recvbuf,
stacksize,
NITEMS,
pclient->pserver->poutfile);
if (status != NITEMS) {
handleLogFileError();
}
status = fprintf(pclient->pserver->poutfile,"\n");
if(status<0){
handleLogFileError();
if (length<0) {
if (errno != EWOULDBLOCK) {
fprintf(stderr,
"%s:%d socket=%d addr=%x size=%d read error=%s\n",
__FILE__, __LINE__, pclient->insock,
pclient->ptopofstack, size, strerror(errno));
freeLogClient(pclient);
}
return;
}
status = fprintf(
pclient->pserver->poutfile,
"%s %s ----- Client Disconnect -----\n",
pclient->name,
pclient->ascii_time);
if(status<0){
handleLogFileError();
else {
/*
* disconnect
*/
freeLogClient(pclient);
return;
}
fdmgr_clear_fd(
pclient->pserver->pfdctx,
pclient->insock);
if(close(pclient->insock)<0)
abort();
free (pclient);
return;
}
pclient->ptopofstack[length] = NULL;
@@ -486,7 +521,76 @@ static void readFromClient(void *pParam)
}
}
/*
* freeLogClient ()
*/
static void freeLogClient(struct iocLogClient *pclient)
{
unsigned stacksize;
int status;
stacksize = pclient->ptopofstack - pclient->recvbuf;
# ifdef DEBUG
if(length == 0){
fprintf(stderr, "iocLogServer: nil message disconnect\n");
}
# endif
/*
* flush any left overs
*/
if(stacksize){
status = fprintf(
pclient->pserver->poutfile,
"%s %s ",
pclient->name,
pclient->ascii_time);
if(status<0){
handleLogFileError();
}
status = fwrite(
pclient->recvbuf,
stacksize,
NITEMS,
pclient->pserver->poutfile);
if (status != NITEMS) {
handleLogFileError();
}
status = fprintf(pclient->pserver->poutfile,"\n");
if(status<0){
handleLogFileError();
}
}
#if 0
status = fprintf(
pclient->pserver->poutfile,
"%s %s ----- Client Disconnect -----\n",
pclient->name,
pclient->ascii_time);
if(status<0){
handleLogFileError();
}
#endif
status = fdmgr_clear_callback(
pclient->pserver->pfdctx,
pclient->insock,
fdi_read);
if (status!=OK) {
fprintf(stderr, "%s:%d fdmgr_clear_callback() failed\n",
__FILE__, __LINE__);
}
if(close(pclient->insock)<0)
abort();
free (pclient);
return;
}
/*
@@ -524,21 +628,23 @@ static int getConfig(void)
{
int status;
char *pstring;
long param;
status = envGetLongConfigParam(
&EPICS_IOC_LOG_PORT,
&ioc_log_port);
if(status<0){
envFailureNotify(&EPICS_IOC_LOG_PORT);
return ERROR;
&param);
if(status>=0){
ioc_log_port = (unsigned short) param;
}
else {
ioc_log_port = 7004U;
}
status = envGetLongConfigParam(
&EPICS_IOC_LOG_FILE_LIMIT,
&ioc_log_file_limit);
if(status<0){
envFailureNotify(&EPICS_IOC_LOG_FILE_LIMIT);
return ERROR;
ioc_log_file_limit = 10000;
}
pstring = envGetConfigParam(