- edg_wll_log_event_write() and edg_wll_log_event_send() calls added into
authorJiří Škrábal <nykolas@ics.muni.cz>
Thu, 3 Mar 2005 12:01:15 +0000 (12:01 +0000)
committerJiří Škrábal <nykolas@ics.muni.cz>
Thu, 3 Mar 2005 12:01:15 +0000 (12:01 +0000)
  common library
  They write event strings to the local socket or to the lokal file

org.glite.lb.common/Makefile
org.glite.lb.common/interface/log_proto.h
org.glite.lb.common/src/log_msg.c [new file with mode: 0644]

index f8bb109..b77ddcd 100644 (file)
@@ -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
index a2a59a8..048630d 100644 (file)
@@ -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 (file)
index 0000000..073360e
--- /dev/null
@@ -0,0 +1,240 @@
+#include <sys/un.h>
+#include <stdio.h>
+
+#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;
+}