Index: src/Makefile.am =================================================================== RCS file: /server/cvs-server/squid/squid/src/Makefile.am,v retrieving revision 1.51 diff -u -r1.51 Makefile.am --- src/Makefile.am 11 Jun 2006 17:06:25 -0000 1.51 +++ src/Makefile.am 16 Jul 2006 13:41:40 -0000 @@ -44,6 +44,8 @@ UNLINKD = endif +LOGFILE_DAEMON = logfile_daemon + if ENABLE_PINGER PINGER = pinger else @@ -84,6 +86,7 @@ EXTRA_PROGRAMS = \ unlinkd \ + logfile_daemon \ pinger \ dnsserver @@ -96,6 +99,7 @@ libexec_PROGRAMS = \ $(PINGER) \ $(DNSSERVER) \ + $(LOGFILE_DAEMON) \ $(UNLINKD) cf_gen_SOURCES = cf_gen.c defines.h debug.c @@ -257,6 +261,11 @@ unlinkd-daemon.o: unlinkd.c $(COMPILE) -DUNLINK_DAEMON -c $(srcdir)/unlinkd.c -o $@ +logfile_daemon_SOURCES = logfile_daemon.c +logfile_daemon.o: logfile_daemon.c + $(COMPILE) -c $(srcdir)/logfile_daemon.c -o $@ + + pinger_SOURCES = \ pinger.c \ debug.c @@ -307,6 +316,7 @@ DEFAULT_SWAP_DIR = $(localstatedir)/cache DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'` +DEFAULT_LOGFILE_DAEMON = $(libexecdir)/`echo logfile_daemon | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_DISKD = $(libexecdir)/`echo diskd_daemon | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_ICON_DIR = $(datadir)/icons DEFAULT_ERROR_DIR = $(datadir)/errors/@ERR_DEFAULT_LANGUAGE@ @@ -353,6 +363,7 @@ s%@DEFAULT_MIME_TABLE@%$(DEFAULT_MIME_TABLE)%g;\ s%@DEFAULT_DNSSERVER@%$(DEFAULT_DNSSERVER)%g;\ s%@DEFAULT_UNLINKD@%$(DEFAULT_UNLINKD)%g;\ + s%@DEFAULT_LOGFILE_DAEMON@%$(DEFAULT_LOGFILE_DAEMON)%g;\ s%@DEFAULT_PINGER@%$(DEFAULT_PINGER)%g;\ s%@DEFAULT_DISKD@%$(DEFAULT_DISKD)%g;\ s%@DEFAULT_CACHE_LOG@%$(DEFAULT_CACHE_LOG)%g;\ Index: src/logfile.c =================================================================== RCS file: /server/cvs-server/squid/squid/src/logfile.c,v retrieving revision 1.16 diff -u -r1.16 logfile.c --- src/logfile.c 5 Jun 2006 21:06:34 -0000 1.16 +++ src/logfile.c 16 Jul 2006 13:41:41 -0000 @@ -34,7 +34,7 @@ #include "squid.h" -static void logfileWriteWrapper(Logfile * lf, const void *buf, size_t len); +#define LOGFILE_BUFSZ 32768 #if HAVE_SYSLOG @@ -48,6 +48,7 @@ int value; } syslog_symbol_t; + static int syslog_ntoa(const char *s) { @@ -115,15 +116,156 @@ #define PRIORITY_MASK (LOG_ERR | LOG_WARNING | LOG_NOTICE | LOG_INFO | LOG_DEBUG) #endif /* HAVE_SYSLOG */ +/* Internal code */ +static void +logfileNewBuffer(Logfile *lf) +{ + logfile_buffer_t *b; + + debug(50, 3) ("logfileNewBuffer: %s: new buffer\n", lf->path); + + b = xcalloc(1, sizeof(logfile_buffer_t)); + assert(b != NULL); + b->buf = xcalloc(1, LOGFILE_BUFSZ); + assert(b->buf != NULL); + b->size = LOGFILE_BUFSZ; + b->written_len = 0; + b->len = 0; + b->full = 0; + dlinkAddTail(b, &b->node, &lf->bufs); + lf->nbufs++; +} + +static void +logfileFreeBuffer(Logfile *lf, logfile_buffer_t *b) +{ + assert(b != NULL); + dlinkDelete(&b->node, &lf->bufs); + lf->nbufs --; + xfree(b->buf); + xfree(b); +} + +static void +logfileHandleWrite(int fd, void *data) +{ + Logfile *lf = (Logfile *) data; + int ret; + logfile_buffer_t *b; + + /* + * We'll try writing the first entry until its done - if we + * get a partial write then we'll re-schedule until its completed. + * Its naive but it'll do for now. + */ + b = lf->bufs.head->data; + assert (b != NULL); + lf->flush_pending = 0; + + ret = FD_WRITE_METHOD(lf->wfd, b->buf + b->written_len, b->len - b->written_len); + debug(50, 3) ("logfileHandleWrite: %s: write returned %d\n", lf->path, ret); + if (ret < 0) { + if (ignoreErrno(errno)) { + /* something temporary */ + goto reschedule; + } + debug(50, 1) ("logfileHandleWrite: %s: error writing (%s)\n", lf->path, xstrerror()); + /* XXX should handle this better */ + fatal("I don't handle this error well!"); + } + if (ret == 0) { + /* error? */ + debug(50, 1) ("logfileHandleWrite: %s: wrote 0 bytes?\n", lf->path); + /* XXX should handle this better */ + fatal("I don't handle this error well!"); + } + + /* ret > 0, so something was written */ + b->written_len += ret; + assert(b->written_len <= b->len); + if (b->written_len == b->len) { + /* written the whole buffer! */ + logfileFreeBuffer(lf, b); + b = NULL; + } + /* Is there more to write? */ + if (lf->bufs.head == NULL) { + goto finish; + } + /* there is, so schedule more */ + +reschedule: + commSetSelect(lf->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0); + lf->flush_pending = 1; +finish: + return; +} + +static void +logfileQueueWrite(void *data) +{ + Logfile *lf = (Logfile *) data; + eventAdd("logfile_flush", logfileQueueWrite, lf, 1.0, 1); + if (lf->flush_pending || lf->bufs.head == NULL) { + return; + } + /* Ok, schedule a write-event */ + commSetSelect(lf->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0); + lf->flush_pending = 1; + debug(5, 2) ("logfileQueueWrite: %s: queue depth = %d\n", lf->path, lf->nbufs); +} + + +static void +logfileAppend(Logfile *lf, char *buf, int len) +{ + logfile_buffer_t *b; + int s; + + /* Is there a buffer? If not, create one */ + if (lf->bufs.head == NULL) { + logfileNewBuffer(lf); + } + debug(50, 3) ("logfileAppend: %s: appending %d bytes\n", lf->path, len); + /* Copy what can be copied */ + while (len > 0) { + b = lf->bufs.tail->data; + debug(50, 3) ("logfileAppend: current buffer has %d of %d bytes before append\n", b->len, b->size); + s = XMIN(len, (b->size - b->len)); + xmemcpy(b->buf + b->len, buf, s); + len = len - s; + buf = buf + s; + b->len = b->len + s; + assert(b->len <= LOGFILE_BUFSZ); + assert(len >= 0); + if (len > 0) { + logfileNewBuffer(lf); + } + } +#if 0 + if (lf->bufs.head != NULL) { + logfileQueueWrite(lf); + } +#endif +} + + +/* External code */ + +CBDATA_TYPE(Logfile); Logfile * logfileOpen(const char *path, size_t bufsz, int fatal_flag) { - Logfile *lf = xcalloc(1, sizeof(*lf)); + Logfile *lf; + const char * args[3]; + CBDATA_INIT_TYPE(Logfile); + lf = cbdataAlloc(Logfile); xstrncpy(lf->path, path, MAXPATHLEN); #if HAVE_SYSLOG if (strcmp(path, "syslog") == 0 || strncmp(path, "syslog:", 7) == 0) { lf->flags.syslog = 1; - lf->fd = -1; + lf->rfd = -1; + lf->wfd = -1; if (path[6] != '\0') { const char *priority = path + 7; char *facility = (char *) strchr(priority, '|'); @@ -138,29 +280,16 @@ } else #endif { - int fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT); - if (DISK_ERROR == fd) { - if (ENOENT == errno && fatal_flag) { - fatalf("Cannot open '%s' because\n" - "\tthe parent directory does not exist.\n" - "\tPlease create the directory.\n", path); - } else if (EACCES == errno && fatal_flag) { - fatalf("Cannot open '%s' for writing.\n" - "\tThe parent directory must be writeable by the\n" - "\tuser '%s', which is the cache_effective_user\n" - "\tset in squid.conf.", path, Config.effectiveUser); - } else { - debug(50, 1) ("logfileOpen: %s: %s\n", path, xstrerror()); - safe_free(lf); - return NULL; - } - } - lf->fd = fd; - if (bufsz > 0) { - lf->buf = xmalloc(bufsz); - lf->bufsz = bufsz; - } + args[0] = "logfile_daemon"; + args[1] = path; + args[2] = NULL; + lf->lpid = ipcCreate(IPC_STREAM, "/home/adrian/work/squid/squid-2.6/src/logfile_daemon", args, "logfile_daemon", &lf->rfd, &lf->wfd); + if (lf->lpid < 0) + fatal("Couldn't start logfile helper"); } + lf->nbufs = 0; + eventAdd("logfile_flush", logfileQueueWrite, lf, 1.0, 1); + if (fatal_flag) lf->flags.fatal = 1; return lf; @@ -170,50 +299,20 @@ logfileClose(Logfile * lf) { logfileFlush(lf); - if (lf->fd >= 0) - file_close(lf->fd); - if (lf->buf) - xfree(lf->buf); - xfree(lf); + fd_close(lf->rfd); + fd_close(lf->wfd); /* Should kill the logfile process! */ + eventDelete(logfileQueueWrite, lf); + cbdataFree(lf); } void logfileRotate(Logfile * lf) { -#ifdef S_ISREG - struct stat sb; -#endif - int i; - char from[MAXPATHLEN]; - char to[MAXPATHLEN]; - assert(lf->path); - if (lf->flags.syslog) - return; -#ifdef S_ISREG - if (stat(lf->path, &sb) == 0) - if (S_ISREG(sb.st_mode) == 0) - return; -#endif debug(0, 1) ("logfileRotate: %s\n", lf->path); - /* Rotate numbers 0 through N up one */ - for (i = Config.Log.rotateNumber; i > 1;) { - i--; - snprintf(from, MAXPATHLEN, "%s.%d", lf->path, i - 1); - snprintf(to, MAXPATHLEN, "%s.%d", lf->path, i); - xrename(from, to); - } - /* Rotate the current log to .0 */ - logfileFlush(lf); - file_close(lf->fd); /* always close */ - if (Config.Log.rotateNumber > 0) { - snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0); - xrename(lf->path, to); - } - /* Reopen the log. It may have been renamed "manually" */ - lf->fd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT); - if (DISK_ERROR == lf->fd && lf->flags.fatal) { - debug(50, 1) ("logfileRotate: %s: %s\n", lf->path, xstrerror()); - fatalf("Cannot open %s: %s", lf->path, xstrerror()); + if (lf->lpid > 0) { + if (kill(lf->lpid, SIGHUP) < 0) { + debug(0, 1) ("logfileRotate: %s: couldn't contact logfile_daemon process: %s\n", lf->path, xstrerror()); + } } } @@ -226,22 +325,8 @@ return; } #endif - if (0 == lf->bufsz) { - /* buffering disabled */ - logfileWriteWrapper(lf, buf, len); - return; - } - if (lf->offset > 0 && lf->offset + len > lf->bufsz) - logfileFlush(lf); - if (len > lf->bufsz) { - /* too big to fit in buffer */ - logfileWriteWrapper(lf, buf, len); - return; - } - /* buffer it */ - xmemcpy(lf->buf + lf->offset, buf, len); - lf->offset += len; - assert(lf->offset <= lf->bufsz); + /* Append this data to the end buffer; create a new one if needed */ + logfileAppend(lf, buf, len); } void @@ -277,25 +362,5 @@ void logfileFlush(Logfile * lf) { - if (0 == lf->offset) - return; - logfileWriteWrapper(lf, lf->buf, (size_t) lf->offset); - lf->offset = 0; -} - -/* - * Aborts with fatal message if write() returns something other - * than its length argument. - */ -static void -logfileWriteWrapper(Logfile * lf, const void *buf, size_t len) -{ - int s; - s = FD_WRITE_METHOD(lf->fd, buf, len); - fd_bytes(lf->fd, s, FD_WRITE); - if (s == len) - return; - if (!lf->flags.fatal) - return; - fatalf("logfileWrite: %s: %s\n", lf->path, xstrerror()); + /* XXX unimplemented for now */ } Index: src/structs.h =================================================================== RCS file: /server/cvs-server/squid/squid/src/structs.h,v retrieving revision 1.491 diff -u -r1.491 structs.h --- src/structs.h 5 Jul 2006 06:52:12 -0000 1.491 +++ src/structs.h 16 Jul 2006 13:41:53 -0000 @@ -553,6 +553,7 @@ #if USE_UNLINKD char *unlinkd; #endif + char *logfile_daemon; char *diskd; #if USE_SSL char *ssl_password; @@ -2409,17 +2410,27 @@ } shm; }; +struct _logfile_buffer { + char *buf; + int size; + int len; + int written_len; + int full; + dlink_node node; +}; + struct _Logfile { - int fd; + int rfd, wfd; char path[MAXPATHLEN]; - char *buf; - size_t bufsz; - ssize_t offset; + dlink_list bufs; + int nbufs; struct { unsigned int fatal; unsigned int syslog; } flags; int syslog_priority; + int flush_pending; + pid_t lpid; }; struct _logformat { Index: src/typedefs.h =================================================================== RCS file: /server/cvs-server/squid/squid/src/typedefs.h,v retrieving revision 1.148 diff -u -r1.148 typedefs.h --- src/typedefs.h 5 Jul 2006 06:52:12 -0000 1.148 +++ src/typedefs.h 16 Jul 2006 13:41:54 -0000 @@ -213,6 +213,7 @@ typedef struct _storefs_entry storefs_entry_t; typedef struct _storerepl_entry storerepl_entry_t; typedef struct _diskd_queue diskd_queue; +typedef struct _logfile_buffer logfile_buffer_t; typedef struct _Logfile Logfile; typedef struct _logformat_token logformat_token; typedef struct _logformat logformat; Index: src/cf.data.pre =================================================================== RCS file: /server/cvs-server/squid/squid/src/cf.data.pre,v retrieving revision 1.357 diff -u -r1.357 cf.data.pre --- src/cf.data.pre 9 Jul 2006 14:39:31 -0000 1.357 +++ src/cf.data.pre 16 Jul 2006 13:42:18 -0000 @@ -1632,6 +1632,14 @@ Specify the location of the executable for file deletion process. DOC_END +NAME: logfile_daemon_program +TYPE: string +DEFAULT: @DEFAULT_LOGFILE_DAEMON@ +LOC: Config.Program.logfile_daemon +DOC_START + Specify the location of the executable for writing to logfiles. +DOC_END + NAME: pinger_program TYPE: string DEFAULT: @DEFAULT_PINGER@