marco@westc.uucp (Marco Nijdam) (10/17/90)
Dear netters, We are writing an application that must keep a log-file of the actions that where taken. It is possible that more than one process writes to a log file at the same time. It would therefore be very convenient that the processes can not write to the same log-file, or even better, that the logging mechanism is intelligent enough to allow several processes to log things in the same file, without causing file corruption. Due to the nature of the application, the logging mechanism must be very reliable. Furthermore, the application will be running on multiple platforms, including Sun and VAX,, so a portable routine it preferred. The application is written in C. I am sure that such a logging mechanism has been written before hundreds of times. So I do not want to invent the wheel all over again. The problem is to find it. Therefore, can anyone give us a lead where I can obtain a routine or library in C that implements the above described logging function, preferably in public domain, or commercial. Or if someone has such a thing lying around, can you send it to me. It must however be royalty free and include source code, so we can maintain it. Also, if you have something that implements only part of our wishes, we are interested. Please reply by email. M.D. Nijdam -- Marco Nijdam, marco@westc.nl OR mcsun!hp4nl!westc!marco -- West Consulting bv, Phoenixstraat 49, 2611 AL Delft, The Netherlands -- P.O. Box 3318, 2601 DH Delft -- Tel: +31-15-123190, Fax: +31-15-147889
mjr@hussar.dco.dec.com (Marcus J. Ranum) (10/18/90)
In article <1990Oct17.094623.2381@westc.uucp> marco@westc.uucp (Marco Nijdam) writes: >We are writing an application that must keep a log-file of the >actions that where taken. It is possible that more than one >process writes to a log file at the same time. Depending on how time-critical the logging function is, you might want to either use a log server (like syslog(), which is already written and comes with most bsd Unixes) - otherwise, you can roll your own by just keeping the file open, attempting to lock it, seeking to the eof, writing, and releasing the lock. Something like: /* don't take this as gospel! for the purpose of example, error checks are omitted. besides, where do you log failures to write to your log ? */ #include <stdio.h> #include <sys/file.h> log(fd,txt) int fd; char *txt; { int rv; int ln = strlen(txt); while(flock(fd,LOCK_EX)) sleep(1); (void)lseek(fd,0L,SEEK_END); rv = (write(fd,txt,ln) == ln); (void)flock(fd,LOCK_UN); return(rv); }
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (10/18/90)
In article <1990Oct17.094623.2381@westc.uucp> marco@westc.uucp (Marco Nijdam) writes: >We are writing an application that must keep a log-file of the >actions that where taken. It is possible that more than one >process writes to a log file at the same time. Not only that, they wanted it *portable*. You're in luck. ANSI C comes pretty close to what you want. Open the log file: FILE *log = fopen(LogFileTitle, "a"); Ensure that the buffer is big enough for the longest message: size_t MaxLogLineLength = {whatever}; char *log_buffer = malloc(MaxLogLineLength+1); After having checked everything, set up the buffer: setvbuf(log, log_buffer, _IOLBF, MaxLogLineLength+1); Now, to write a record to the log file: fprintf(log, "{format}\n, {arguments}); What's going on here? The "a" argument of fopen() says "the file position indicator is positioned at the end of the file before EACH write". Making the buffer big enough for the longest line and selecting line buffering ensures that each time you write a line using fprintf(), the whole line will be buffered and then sent out. You really need to check the fine print, but this *should* work reasonably well. That is, after all, why "a" is defined the way it is. For anything more reliable, you will have to rely on file locking. -- Fear most of all to be in error. -- Kierkegaard, quoting Socrates.
scs@adam.mit.edu (Steve Summit) (10/23/90)
In article <1990Oct17.094623.2381@westc.uucp> marco@westc.uucp (Marco Nijdam) writes: >We are writing an application that must keep a log-file of the >actions that where taken. It is possible that more than one >process writes to a log file at the same time. In article <4006@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: >Not only that, they wanted it *portable*. >You're in luck. ANSI C comes pretty close to what you want. [Suggests using fopen "a" mode and setvbuf() to select line buffering, with a large buffer.] >What's going on here? The "a" argument of fopen() says "the file position >indicator is positioned at the end of the file before EACH write". Making >the buffer big enough for the longest line and selecting line buffering >ensures that each time you write a line using fprintf(), the whole line >will be buffered and then sent out. > >You really need to check the fine print, but this *should* work reasonably >well. That is, after all, why "a" is defined the way it is. For anything >more reliable, you will have to rely on file locking. I was going to suggest a similar approach, as an approximate solution, but I'm afraid that the "fine print" does not ensure that this will work. First of all, there is no guarantee that buffered output is written with a single call to the underlying operating system (write(2) or the equivalent for Unix). (Actually, section 4.9.3 comes closer than I would have thought, saying that line-buffered "characters are intended to be transmitted to... the host environment as a block," although that's "when a new-line character is encountered.") Secondly, there is no guarantee that the underlying operating system's low-level write mechanism is atomic. (Unix's tends to be, at least for "reasonably" sized requests.) As Richard mentions, file locking is the more reliable approach, though obviously less portable. (In practice, his suggested mechanism will probably work fine, at least on a Unix system. Beware of older Unix systems, for which fopen "a" mode indicated a seek to the end at open time, with no special attention thereafter, whereas this application requires the equivalent of open(2)'s O_APPEND mode, indicating a seek to the end upon each write.) Steve Summit scs@adam.mit.edu