[collectd] [PATCH] src/utils_tail.[ch]: Created a generic interface for reading files in a tail-like fashion.

Florian Forster octo at home.verplant.org
Sat Nov 24 14:20:14 CET 2007


Luke Heberling is working on plugins that need to read logfiles. Hopefully this
code supports him doing that. So far this code is untested.

The interface is fairly simple:
- create  creates an (opaque) `tail object' which is associated with a
          filename/path.
- destroy destroys/frees the object.
- open    opens the file, locks the file (from the last position to the end of
          file), seeks to the last position and returns the filehandle.
- close   saves the current position and closes the file.
---
 src/Makefile.am  |    1 +
 src/utils_tail.c |  161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/utils_tail.h |   76 +++++++++++++++++++++++++
 3 files changed, 238 insertions(+), 0 deletions(-)
 create mode 100644 src/utils_tail.c
 create mode 100644 src/utils_tail.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 06f45dc..b3c65ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,7 @@ collectd_SOURCES = collectd.c collectd.h \
 		   utils_ignorelist.c utils_ignorelist.h \
 		   utils_llist.c utils_llist.h \
 		   utils_mount.c utils_mount.h \
+		   utils_tail.c utils_tail.h \
 		   utils_threshold.c utils_threshold.h \
 		   types_list.c types_list.h
 collectd_CPPFLAGS = $(LTDLINCL)
diff --git a/src/utils_tail.c b/src/utils_tail.c
new file mode 100644
index 0000000..13b5fb5
--- /dev/null
+++ b/src/utils_tail.c
@@ -0,0 +1,161 @@
+/**
+ * collectd - src/utils_tail.c
+ * Copyright (C) 2007  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Author:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_tail.h"
+
+struct cu_tail_s
+{
+  char  *file;
+  FILE  *fh;
+  off_t  pos;
+};
+
+cu_tail_t *cu_tail_create (const char *file)
+{
+  cu_tail_t *obj;
+
+  obj = (cu_tail_t *) malloc (sizeof (cu_tail_t));
+  if (obj == NULL)
+    return (NULL);
+  memset (obj, '\0', sizeof (cu_tail_t));
+
+  obj->file = strdup (file);
+  if (obj->file == NULL)
+  {
+    sfree (obj);
+    return (NULL);
+  }
+
+  return (obj);
+} /* cu_tail_t *cu_tail_create */
+
+int cu_tail_destroy (cu_tail_t *obj)
+{
+  if (obj == NULL)
+    return (-1);
+
+  if (obj->fh != NULL)
+  {
+    fclose (obj->fh);
+    obj->fh = NULL;
+  }
+
+  sfree (obj->file);
+  sfree (obj);
+
+  return (0);
+} /* int cu_tail_destroy */
+
+FILE *cu_tail_open (cu_tail_t *obj)
+{
+  struct flock lock;
+  int status;
+
+  if (obj == NULL)
+    return (NULL);
+  if (obj->fh != NULL)
+    return (NULL);
+
+  obj->fh = fopen (obj->file, "r");
+  if (obj->fh == NULL)
+  {
+    char errbuf[256];
+    ERROR ("cu_tail_open: fopen (%s) failed: %s", obj->file,
+	sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (NULL);
+  }
+
+  memset (&lock, '\0', sizeof (lock));
+  lock.l_type = F_RDLCK;
+  lock.l_whence = SEEK_SET;
+  lock.l_start = obj->pos;
+  lock.l_len = 0; /* everything until the end of file */
+
+  /* Warning: `fileno' may not be portable */
+  status = fcntl (fileno (obj->fh), F_SETLK, &lock);
+  if (status != 0)
+  {
+    char errbuf[256];
+    fclose (obj->fh);
+    obj->fh = NULL;
+    WARNING ("cu_tail_open: fcntl (%s) failed: %s", obj->file,
+	sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (NULL);
+  }
+
+  status = fseeko (obj->fh, obj->pos, SEEK_SET);
+  if (status != 0)
+  {
+    status = fseeko (obj->fh, 0, SEEK_SET);
+    if (status != 0)
+    {
+      char errbuf[256];
+      ERROR ("cu_tail_open: fseeko (%s) failed: %s",
+	  obj->file, sstrerror (errno, errbuf, sizeof (errbuf)));
+      fclose (obj->fh);
+      obj->fh = NULL;
+      return (NULL);
+    }
+    else
+    {
+      INFO ("cu_tail_open: Apparently file `%s' was trunkated.",
+	  obj->file);
+    }
+  }
+
+  return (obj->fh);
+} /* FILE *cu_tail_open */
+
+int cu_tail_close (cu_tail_t *obj)
+{
+  off_t pos;
+  int status = 0;
+
+  if (obj == NULL)
+    return (-1);
+  if (obj->fh == NULL)
+    return (-1);
+
+  pos = ftello (obj->fh);
+  if (pos < 0)
+  {
+    char errbuf[256];
+    ERROR ("cu_tail_close: ftello (%s) failed: %s",
+	obj->file, sstrerror (errno, errbuf, sizeof (errbuf)));
+    status = -1;
+  }
+  else
+  {
+    obj->pos = pos;
+  }
+
+  if (fclose (obj->fh) != 0)
+    status = -1;
+  obj->fh = NULL;
+
+  return (status);
+} /* int cu_tail_close */
+
+/* vim: set shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker : */
diff --git a/src/utils_tail.h b/src/utils_tail.h
new file mode 100644
index 0000000..b5adcb9
--- /dev/null
+++ b/src/utils_tail.h
@@ -0,0 +1,76 @@
+/**
+ * collectd - src/utils_tail.h
+ * Copyright (C) 2007  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Author:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef UTILS_TAIL_H
+#define UTILS_TAIL_H 1
+
+#include "collectd.h"
+
+struct cu_tail_s;
+typedef struct cu_tail_s cu_tail_t;
+
+/*
+ * cu_tail_create
+ *
+ * Creates and returnes a `cu_tail_t' object associated with the file given as
+ * argument. This structure should be destroyed with `cu_tail_destroy' (see
+ * below).
+ *
+ * Returns NULL upon failure.
+ */
+cu_tail_t *cu_tail_create (const char *file);
+
+/*
+ * cu_tail_destroy
+ *
+ * Takes a tail object returned by `cu_tail_create' and destroys it, freeing
+ * all internal memory.
+ *
+ * Returns 0 when successful and non-zero otherwise.
+ */
+int cu_tail_destroy (cu_tail_t *obj);
+
+/*
+ * cu_tail_open
+ *
+ * Opens the file associated with the tail object, seeks to the last known
+ * position (or the beginning of the file, if it has been truncated since last
+ * opening it) and returns the filehandle.
+ * This will fail (i. e. return NULL) if the file is already opened by the
+ * object.
+ *
+ * Returns the filehandle or NULL if an error occurred.
+ */
+FILE *cu_tail_open (cu_tail_t *obj);
+
+/*
+ * cu_tail_close
+ *
+ * Stores the current position in the file and closes the filehandle of the
+ * tail object. After that, you can call `cu_tail_open' again.
+ *
+ * Returns 0 when successful and non-zero otherwise.
+ */
+int cu_tail_close (cu_tail_t *obj);
+
+#endif /* UTILS_TAIL_H */
+
+/* vim: set shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker : */
-- 
1.5.3.5




More information about the collectd mailing list