summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoern Engel <joern@logfs.org>2015-02-17 11:13:15 -0800
committerJoern Engel <joern@logfs.org>2015-02-17 11:50:09 -0800
commite3b0e34a3ea0cd91118345f9dca7242ad2083736 (patch)
treec7187e5dad0dc3e36b8329e5e092c0f21459649e
parentbbb023f21912ab5c23201834a74a091222d308e2 (diff)
downloadcancd-e3b0e34a3ea0cd91118345f9dca7242ad2083736.tar.gz
Cache open/stat for performance
Open fd stays valid for 60s. It will actually stick around forever, there is no garbage collection for stale files yet. Signed-off-by: Joern Engel <joern@logfs.org>
-rw-r--r--cancd.c66
1 files changed, 51 insertions, 15 deletions
diff --git a/cancd.c b/cancd.c
index ebd8bdd..4538f6c 100644
--- a/cancd.c
+++ b/cancd.c
@@ -105,6 +105,9 @@ struct source_ip {
const char *filename;
const char *tmpfilename;
int had_newline;
+ int fd;
+ uint64_t filesize;
+ uint64_t reopen_time;
};
void handler(int signum)
@@ -322,7 +325,7 @@ static int do_write(int fd, const void *buf, size_t count)
return 0;
}
-static int write_formatted(int fd, struct source_ip *sip, char *buf, int count)
+static int write_formatted(struct source_ip *sip, char *buf, int count)
{
const char *format = "%b %d %H:%M:%S ";
char *end;
@@ -340,19 +343,21 @@ static int write_formatted(int fd, struct source_ip *sip, char *buf, int count)
while (count > 1) {
if (sip->had_newline) {
n = strftime(timestr, sizeof(timestr), format, tm);
- err = do_write(fd, timestr, n);
+ err = do_write(sip->fd, timestr, n);
if (err)
return err;
}
end = strchr(buf, 0xa);
if (!end) {
/* no newline, just write what we have */
- do_write(fd, buf, count - 1);
+ err = do_write(sip->fd, buf, count - 1);
+ if (err)
+ return err;
sip->had_newline = 0;
break;
}
len = end - buf + 1;
- err = do_write(fd, buf, len);
+ err = do_write(sip->fd, buf, len);
if (err)
return err;
buf += len;
@@ -372,6 +377,7 @@ static struct source_ip *get_source_ip(struct sockaddr_in *addr)
if (!sip) {
sip = calloc(1, sizeof(*sip));
sip->had_newline = 1;
+ sip->fd = -1;
sip->tmpfilename = get_path(&addr->sin_addr);
err = btree_insert32(&btree, key, sip);
assert(!err);
@@ -398,6 +404,10 @@ static const char *copy_tmpfile(struct source_ip *sip)
char buf[4096];
ssize_t count;
+ if (sip->fd >= 0) {
+ close(sip->fd);
+ sip->fd = -1;
+ }
fd = open(name, O_WRONLY | O_APPEND | O_CREAT, 0644);
if (fd < 0) {
syslog(LOG_ERR, "Unable to open \"%s\": %s", name,
@@ -427,9 +437,17 @@ out:
return NULL;
}
+uint64_t gethrtime(void)
+{
+ struct timespec tod;
+
+ clock_gettime(CLOCK_MONOTONIC, &tod);
+ return tod.tv_sec * 1000000000ULL + tod.tv_nsec;
+}
+
static void do_output(char *buf, int len, struct sockaddr_in *addr, socklen_t socklen)
{
- int fd, err;
+ int err;
struct stat stat;
const char *name;
struct source_ip *sip = get_source_ip(addr);
@@ -438,17 +456,35 @@ static void do_output(char *buf, int len, struct sockaddr_in *addr, socklen_t so
if (!name)
return;
- fd = open(name, O_WRONLY | O_APPEND | O_CREAT, 0644);
- if (fd < 0) {
- syslog(LOG_ERR, "Unable to open \"%s\": %s", name, strerror(errno));
- return;
+ /*
+ * We cache the open fd for 60s. We also cache the filesize.
+ * This reduces cpu overhead a bit, but means logrotate has to
+ * keep the file around for 60s after rotation and we can
+ * overshoot the size limit a bit.
+ */
+ if (sip->fd >= 0 && gethrtime() > sip->reopen_time) {
+ close(sip->fd);
+ sip->fd = -1;
}
- err = fstat(fd, &stat);
- if (err || stat.st_size > size_limit)
- goto out;
- write_formatted(fd, sip, buf, len);
-out:
- close(fd);
+
+ if (sip->fd < 0) {
+ sip->fd = open(name, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ if (sip->fd < 0) {
+ syslog(LOG_ERR, "Unable to open \"%s\": %s", name, strerror(errno));
+ return;
+ }
+ err = fstat(sip->fd, &stat);
+ if (err) {
+ close(sip->fd);
+ sip->fd = -1;
+ return;
+ }
+ sip->filesize = stat.st_size;
+ sip->reopen_time = gethrtime() + 60000000000ULL; /* 60s */
+ }
+ if (sip->filesize > size_limit)
+ return;
+ write_formatted(sip, buf, len);
}
static int set_blocking(int blocking)