22 #define EPICS_PRIVATE_API 42 struct sockaddr_in addr;
59 static const double LOG_SERVER_SHUTDOWN_TIMEOUT = 30.0;
64 static char* logClientPrefix =
NULL;
69 static void logClientClose (
logClient *pClient )
72 fprintf (
stderr,
"log client: lingering for connection close...");
97 fprintf (
stderr,
"done\n");
120 switch ( interruptInfo ) {
122 logClientClose ( pClient );
142 LOG_SERVER_SHUTDOWN_TIMEOUT / 10.0 );
147 while ( ! pClient->
shutdownConfirm && diff < LOG_SERVER_SHUTDOWN_TIMEOUT );
151 fprintf (
stderr,
"log client shutdown: timed out stopping reconnect\n" 152 " thread for '%s' after %.1f seconds - cleanup aborted\n",
153 pClient->
name, LOG_SERVER_SHUTDOWN_TIMEOUT );
157 logClientClose ( pClient );
169 static void sendMessageChunk(
logClient * pClient,
const char * message) {
172 strSize = strlen ( message );
174 unsigned msgBufBytesLeft =
177 if ( msgBufBytesLeft < strSize && pClient->nextMsgIndex != 0u && pClient->
connected)
183 if ( msgBufBytesLeft == 0u ) {
184 fprintf (
stderr,
"log client: messages to \"%s\" are lost\n",
188 if ( msgBufBytesLeft > strSize) msgBufBytesLeft = strSize;
190 message, msgBufBytesLeft );
192 strSize -= msgBufBytesLeft;
193 message += msgBufBytesLeft;
204 if ( ! pClient || ! message ) {
210 if (logClientPrefix) {
211 sendMessageChunk(pClient, logClientPrefix);
213 sendMessageChunk(pClient, message);
226 if ( ! pClient || ! pClient->
connected ) {
233 while ( nSent < pClient->nextMsgIndex && pClient->
connected ) {
234 status = send ( pClient->
sock, pClient->
msgBuf + nSent,
236 if ( status < 0 )
break;
240 if ( pClient->
backlog > 0 && status >= 0 ) {
244 status = send ( pClient->
sock,
NULL, 0, 0 );
250 char sockErrBuf[128];
252 fprintf(
stderr,
"log client: lost contact with log server at '%s'\n" 253 " because \"%s\"\n", pClient->
name, sockErrBuf);
256 logClientClose ( pClient );
276 static void logClientMakeSock (
logClient *pClient)
279 fprintf (
stderr,
"log client: creating socket...");
290 char sockErrBuf[128];
292 sockErrBuf,
sizeof ( sockErrBuf ) );
293 fprintf (
stderr,
"log client: no socket error %s\n",
300 fprintf (
stderr,
"done\n");
306 static void logClientConnect (
logClient *pClient)
313 logClientMakeSock ( pClient );
320 status = connect (pClient->
sock,
321 (
struct sockaddr *)&pClient->
addr,
sizeof(pClient->
addr));
340 char sockErrBuf[128];
342 sockErrBuf,
sizeof ( sockErrBuf ) );
344 "log client: failed to connect to server '%s'" 346 pClient->
name, sockErrBuf);
349 logClientClose ( pClient );
365 status = setsockopt (pClient->
sock, SOL_SOCKET, SO_KEEPALIVE,
366 (
char *)&optval,
sizeof(optval));
368 char sockErrBuf[128];
370 sockErrBuf,
sizeof ( sockErrBuf ) );
371 fprintf (
stderr,
"log client: unable to enable SO_KEEPALIVE\n" 372 " because '%s'\n", sockErrBuf);
381 char sockErrBuf[128];
383 sockErrBuf,
sizeof ( sockErrBuf ) );
384 fprintf (
stderr,
"%s:%d shutdown(sock,SHUT_RD) error was '%s'\n",
385 __FILE__, __LINE__, sockErrBuf);
396 struct linger lingerval;
398 lingerval.l_onoff =
TRUE;
399 lingerval.l_linger = 60*5;
400 status = setsockopt (pClient->
sock, SOL_SOCKET, SO_LINGER,
401 (
char *) &lingerval,
sizeof(lingerval));
403 char sockErrBuf[128];
405 sockErrBuf,
sizeof ( sockErrBuf ) );
406 fprintf(
stderr,
"log client: unable to set SO_LINGER\n" 407 " because '%s'\n", sockErrBuf);
417 fprintf(
stderr,
"log client: connected to log server at '%s'\n",
437 if ( ! isConn ) logClientConnect ( pClient );
454 struct in_addr server_addr,
unsigned short server_port)
458 pClient = calloc (1,
sizeof (*pClient));
463 pClient->
addr.sin_family = AF_INET;
464 pClient->
addr.sin_addr = server_addr;
465 pClient->
addr.sin_port = htons(server_port);
469 if ( ! pClient->
mutex ) {
500 logClientRestart, pClient );
506 fprintf(
stderr,
"log client: unable to start reconnection thread\n");
510 return (
void *) pClient;
521 printf (
"log client: connected to log server at '%s'\n", pClient->
name);
524 printf (
"log client: disconnected from log server at '%s'\n",
528 if (logClientPrefix) {
529 printf (
"log client: prefix is \"%s\"\n", logClientPrefix);
533 printf (
"log client: sock %s, connect cycles = %u\n",
540 printf(
"-------------------------\n" 541 "%.*s-------------------------\n",
558 if (logClientPrefix) {
559 printf (
"iocLogPrefix: The prefix was already set to \"%s\" " 560 "and can't be changed.\n", logClientPrefix);
565 unsigned prefixLen = strlen(prefix);
567 char * localCopy = malloc(prefixLen+1);
568 strcpy(localCopy, prefix);
569 logClientPrefix = localCopy;
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
void epicsStdCall epicsMutexDestroy(epicsMutexId pmutexNode)
Destroy an epicsMutex semaphore.
An EPICS-specific replacement for ANSI C's assert.
epicsExportAddress(int, logClientDebug)
int epicsSocketUnsentCount(SOCKET sock)
LIBCOM_API void epicsStdCall epicsSignalRaiseSigAlarm(struct epicsThreadOSD *)
enum epicsSocketSystemCallInterruptMechanismQueryInfo epicsSocketSystemCallInterruptMechanismQuery()
void epicsStdCall logClientSend(logClientId id, const char *message)
epicsEventId stateChangeNotify
LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut)
Wait an the event or until the specified timeout period is over.
void epicsStdCall logClientFlush(logClientId id)
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Miscellaneous macro definitions.
epicsSocketSystemCallInterruptMechanismQueryInfo
LIBCOM_API unsigned int epicsStdCall epicsThreadGetStackSize(epicsThreadStackSizeClass size)
epicsThreadId epicsStdCall epicsThreadCreate(const char *name, unsigned int priority, unsigned int stackSize, EPICSTHREADFUNC funptr, void *parm)
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
LIBCOM_API SOCKET epicsStdCall epicsSocketCreate(int domain, int type, int protocol)
#define epicsEventSignal(ID)
A synonym for epicsEventTrigger().
APIs for the epicsMutex mutual exclusion semaphore.
epicsEventId shutdownNotify
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
#define epicsThreadPriorityLow
Extended replacement for the Posix exit and atexit routines.
LIBCOM_API void epicsEventDestroy(epicsEventId id)
Destroy an epicsEvent and any resources it holds.
APIs for the epicsEvent binary semaphore.
void epicsStdCall iocLogPrefix(const char *prefix)
EPICS time stamp, for use from C code.
#define LOG_RESTART_DELAY
#define epicsMutexCreate()
Create an epicsMutex semaphore for use from C code.
LIBCOM_API double epicsStdCall epicsTimeDiffInSeconds(const epicsTimeStamp *pLeft, const epicsTimeStamp *pRight)
Time difference between left and right in seconds.
OS-independent routines for ignoring Posix signals.
EPICS time-stamps (epicsTimeStamp), epicsTime C++ class and C functions for handling wall-clock times...
#define epicsAtExit(F, A)
Convenience macro to register a function and context value to be run when the process exits...
logClientId epicsStdCall logClientCreate(struct in_addr server_addr, unsigned short server_port)
C++ and C descriptions for a thread.
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).
void epicsStdCall logClientShow(logClientId id, unsigned level)
LIBCOM_API epicsEventId epicsEventCreate(epicsEventInitialState initialState)
Create an epicsEvent for use from C code, or return NULL.
epicsThreadId restartThreadId
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)