From: Jiří Škrábal Date: Thu, 3 Mar 2005 12:01:15 +0000 (+0000) Subject: - edg_wll_log_event_write() and edg_wll_log_event_send() calls added into X-Git-Tag: glite-deployment-lb_R_1_1_1~34 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=0aaffbc47d02c114708c2bf071eb109562c1280d;p=jra1mw.git - edg_wll_log_event_write() and edg_wll_log_event_send() calls added into common library They write event strings to the local socket or to the lokal file --- diff --git a/org.glite.lb.common/Makefile b/org.glite.lb.common/Makefile index f8bb109..b77ddcd 100644 --- a/org.glite.lb.common/Makefile +++ b/org.glite.lb.common/Makefile @@ -83,15 +83,15 @@ INSTALL:=libtool --mode=install install OBJS:=lb_plain_io.o escape.o events.o mini_http.o query_rec.o \ status.o xml_conversions.o xml_parse.o ulm_parse.o param.o \ events_parse.o il_string.o il_int.o notifid.o \ - il_log.o il_msg.o context.o trio.o strio.o + il_log.o il_msg.o log_msg.o context.o trio.o strio.o LOBJS:=${OBJS:.o=.lo} THROBJS:=${OBJS:.o=.thr.o} THRLOBJS:=${OBJS:.o=.thr.lo} HDRS:=context-int.h lb_plain_io.h mini_http.h authz.h xml_parse.h \ - xml_conversions.h log_proto.h events_parse.h il_string.h il_msg.h escape.h \ - ulm_parse.h trio.h + xml_conversions.h log_proto.h events_parse.h il_string.h il_msg.h \ + escape.h ulm_parse.h trio.h STATICLIB:=libglite_lb_common_${nothrflavour}.a THRSTATICLIB:=libglite_lb_common_${thrflavour}.a diff --git a/org.glite.lb.common/interface/log_proto.h b/org.glite.lb.common/interface/log_proto.h index a2a59a8..048630d 100644 --- a/org.glite.lb.common/interface/log_proto.h +++ b/org.glite.lb.common/interface/log_proto.h @@ -69,8 +69,32 @@ extern "C" { #define EDG_WLL_LOG_CONNECTIONS_DEFAULT 4 + #ifdef __cplusplus } #endif +/* + * Functions which manage communication with interlogger. + * (especially used in local logger when sending events to ilogd) + */ +extern int +edg_wll_log_event_write( + edg_wll_Context ctx, + const char *event_file, + const char *msg, + unsigned int fcntl_attempts, + unsigned int fcntl_timeout, + long *filepos); + +extern int +edg_wll_log_event_send( + edg_wll_Context ctx, + const char *socket_path, + long filepos, + const char *msg, + int msg_size, + int conn_attempts, + struct timeval *timeout); + #endif /* __EDG_WORKLOAD_LOGGING_COMMON_LOG_PROTO_H__ */ diff --git a/org.glite.lb.common/src/log_msg.c b/org.glite.lb.common/src/log_msg.c new file mode 100644 index 0000000..073360e --- /dev/null +++ b/org.glite.lb.common/src/log_msg.c @@ -0,0 +1,240 @@ +#include +#include + +#include "glite/lb/context-int.h" + +#define tv_sub(a, b) {\ + (a).tv_usec -= (b).tv_usec;\ + (a).tv_sec -= (b).tv_sec;\ + if ((a).tv_usec < 0) {\ + (a).tv_sec--;\ + (a).tv_usec += 1000000;\ + }\ +} + + +/*! + * Write to socket + * Needn't write entire buffer. Timeout is applicable only for non-blocking + * connections + * \param sock IN: connection to work with + * \param buf IN: buffer + * \param bufsize IN: max size to write + * \param timeout INOUT: max time allowed for operation, remaining time on return + * \retval bytes written (>0) on success + * \retval -1 on write error + */ +static ssize_t +edg_wll_socket_write( + int sock, + const void *buf, + size_t bufsize, + struct timeval *timeout) +{ + ssize_t len = 0; + fd_set fds; + struct timeval to, before, after; + + + if ( timeout ) { + memcpy(&to, timeout, sizeof to); + gettimeofday(&before, NULL); + } + len = write(sock, buf, bufsize); + while ( len <= 0 ) { + FD_ZERO(&fds); + FD_SET(sock,&fds); + if ( select(sock+1, &fds,NULL,NULL, timeout? &to: NULL) < 0 ) return -1; + len = write(sock, buf, bufsize); + } + if ( timeout ) { + gettimeofday(&after, NULL); + tv_sub(after, before); + tv_sub(*timeout, after); + if ( timeout->tv_sec < 0 ) { + timeout->tv_sec = 0; + timeout->tv_usec = 0; + } + } + + return len; +} + +/*! + * Write specified amount of data to socket + * Attempts to call edg_wll_socket_write() untill the entire request is satisfied + * (or times out). + * \param sock IN: connection to work with + * \param buf IN: buffer + * \param bufsize IN: max size to write + * \param timeout INOUT: max time allowed for operation, remaining time on return + * \param total OUT: bytes actually written + * \retval bytes written (>0) on success + * \retval -1 on write error + */ +static ssize_t +edg_wll_socket_write_full( + int sock, + void *buf, + size_t bufsize, + struct timeval *timeout, + ssize_t *total) +{ + ssize_t len; + *total = 0; + + while ( *total < bufsize ) { + len = edg_wll_socket_write(sock, buf+*total, bufsize-*total, timeout); + if (len < 0) return len; + *total += len; + } + + return 0; +} + +/* + * edg_wll_log_event_write - write event to the local file + * + * Returns: 0 if done properly or errno + * + */ +int edg_wll_log_event_write( + edg_wll_Context ctx, + const char *event_file, + const char *msg, + unsigned int fcntl_attempts, + unsigned int fcntl_timeout, + long *filepos) +{ + FILE *outfile; + struct flock filelock; + int filedesc, + i, filelock_status=-1; + + + for ( i = 0; i < fcntl_attempts; i++ ) { + if ( (outfile = fopen(event_file, "a")) == NULL ) { + edg_wll_SetError(ctx, errno, "fopen()"); + goto event_write_end; + } + + if ( (filedesc = fileno(outfile)) == -1 ) { + edg_wll_SetError(ctx, errno, "fileno()"); + fclose(outfile); + goto cleanup; + } + + filelock.l_type = F_WRLCK; + filelock.l_whence = SEEK_SET; + filelock.l_start = 0; + filelock.l_len = 0; + + if ( (filelock_status = fcntl(filedesc, F_SETLK, &filelock) < 0) ) { + switch(errno) { + case EAGAIN: + case EACCES: + case EINTR: + sleep(fcntl_timeout); + break; + default: + edg_wll_SetError(ctx, errno, "fcntl()"); + goto cleanup; + } + } + } + + if ( fseek(outfile, 0, SEEK_END) == -1 ) { + edg_wll_SetError(ctx, errno, "fseek()"); + goto cleanup; + } + if ( (*filepos = ftell(outfile)) == -1 ) { + edg_wll_SetError(ctx, errno, "ftell()"); + goto cleanup; + } + if ( fputs(msg, outfile) == EOF ) { + edg_wll_SetError(ctx, errno, "fputs()"); + goto cleanup; + } + if ( fflush(outfile) == EOF ) { + edg_wll_SetError(ctx, errno, "fflush()"); + goto cleanup; + } + if ( fsync(filedesc) < 0 ) { + edg_wll_SetError(ctx, errno, "fsync()"); + goto cleanup; + } + + +cleanup: + fclose(outfile); + +event_write_end: + return edg_wll_Error(ctx, NULL, NULL)? edg_wll_Error(ctx, NULL, NULL): 0; + +} + +/* + * edg_wll_log_event_send - send event to the socket + * + * Returns: 0 if done properly or errno + * + */ +int edg_wll_log_event_send( + edg_wll_Context ctx, + const char *socket_path, + long filepos, + const char *msg, + int msg_size, + int conn_attempts, + struct timeval *timeout) +{ + struct sockaddr_un saddr; + int msg_sock, + flags, + i, count = 0; + + + if ( (msg_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) { + edg_wll_SetError(ctx, errno, "socket()"); + goto event_send_end; + } + + memset(&saddr, 0, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + strcpy(saddr.sun_path, socket_path); + + if ( (flags = fcntl(msg_sock, F_GETFL, 0)) < 0 + || fcntl(msg_sock, F_SETFL, flags | O_NONBLOCK) < 0 ) { + edg_wll_SetError(ctx, errno, "fcntl()"); + goto cleanup; + } + + for ( i = 0; i < conn_attempts; i++) { + if ( connect(msg_sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0 ) { + if ( errno == EISCONN ) break; + else if ((errno == EAGAIN) || (errno == ETIMEDOUT)) { + sleep(timeout->tv_sec); + continue; + } else { + edg_wll_SetError(ctx, errno, "connect()"); + goto cleanup; + } + } else break; + } + + if ( edg_wll_socket_write_full(msg_sock, &filepos, sizeof(filepos), timeout, &count) < 0 ) { + edg_wll_SetError(ctx, errno, "edg_wll_socket_write_full()"); + goto cleanup; + } + + if ( edg_wll_socket_write_full(msg_sock, (void *)msg, msg_size, timeout, &count) < 0 ) { + edg_wll_SetError(ctx, errno, "edg_wll_socket_write_full()"); + goto cleanup; + } + +cleanup: + close(msg_sock); + +event_send_end: + return edg_wll_Error(ctx, NULL, NULL)? edg_wll_Error(ctx, NULL, NULL): 0; +}