summaryrefslogtreecommitdiffstats
path: root/xlators/features/changelog
diff options
context:
space:
mode:
authorJeff Darcy <jdarcy@redhat.com>2014-04-28 14:18:50 +0000
committerJeff Darcy <jdarcy@redhat.com>2014-04-28 14:18:50 +0000
commite139b4d0ba2286c0d4d44ba81260c2b287016019 (patch)
tree0a21f0761528e0f79da0a9f67106eb128ace0cf7 /xlators/features/changelog
parent73b60c87ca7f62517a8466431f5a8cf167589c8c (diff)
parentf2bac9f9d5b9956969ddd25a54bc636b82f6923e (diff)
Merge branch 'upstream'HEADmaster
Conflicts: rpc/xdr/src/glusterfs3-xdr.c rpc/xdr/src/glusterfs3-xdr.h xlators/features/changelog/src/Makefile.am xlators/features/changelog/src/changelog-helpers.h xlators/features/changelog/src/changelog.c xlators/mgmt/glusterd/src/glusterd-sm.c Change-Id: I9972a5e6184503477eb77a8b56c50a4db4eec3e2
Diffstat (limited to 'xlators/features/changelog')
-rw-r--r--xlators/features/changelog/lib/src/Makefile.am3
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-helpers.h4
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog.c57
-rw-r--r--xlators/features/changelog/lib/src/gf-history-changelog.c274
-rw-r--r--xlators/features/changelog/src/Makefile.am2
-rw-r--r--xlators/features/changelog/src/changelog-helpers.h10
-rw-r--r--xlators/features/changelog/src/changelog.c3
7 files changed, 344 insertions, 9 deletions
diff --git a/xlators/features/changelog/lib/src/Makefile.am b/xlators/features/changelog/lib/src/Makefile.am
index 775f026cf..28d5a70aa 100644
--- a/xlators/features/changelog/lib/src/Makefile.am
+++ b/xlators/features/changelog/lib/src/Makefile.am
@@ -17,7 +17,8 @@ lib_LTLIBRARIES = libgfchangelog.la
CONTRIB_BUILDDIR = $(top_builddir)/contrib
libgfchangelog_la_SOURCES = gf-changelog.c gf-changelog-process.c \
- gf-changelog-helpers.c $(CONTRIBDIR)/uuid/clear.c \
+ gf-changelog-helpers.c gf-history-changelog.c \
+ $(CONTRIBDIR)/uuid/clear.c \
$(CONTRIBDIR)/uuid/copy.c $(CONTRIBDIR)/uuid/gen_uuid.c \
$(CONTRIBDIR)/uuid/pack.c $(CONTRIBDIR)/uuid/parse.c \
$(CONTRIBDIR)/uuid/unparse.c $(CONTRIBDIR)/uuid/uuid_time.c \
diff --git a/xlators/features/changelog/lib/src/gf-changelog-helpers.h b/xlators/features/changelog/lib/src/gf-changelog-helpers.h
index e4cf506c4..fa0edabf0 100644
--- a/xlators/features/changelog/lib/src/gf-changelog-helpers.h
+++ b/xlators/features/changelog/lib/src/gf-changelog-helpers.h
@@ -23,6 +23,7 @@
#define GF_CHANGELOG_CURRENT_DIR ".current"
#define GF_CHANGELOG_PROCESSED_DIR ".processed"
#define GF_CHANGELOG_PROCESSING_DIR ".processing"
+#define GF_CHANGELOG_HISTORY_DIR ".history"
#ifndef MAXLINE
#define MAXLINE 4096
@@ -68,6 +69,9 @@ typedef struct gf_changelog {
char gfc_processing_dir[PATH_MAX];
pthread_t gfc_changelog_processor;
+
+ /* Holds gfc for History API */
+ struct gf_changelog *hist_gfc;
} gf_changelog_t;
int
diff --git a/xlators/features/changelog/lib/src/gf-changelog.c b/xlators/features/changelog/lib/src/gf-changelog.c
index 4b2b25ad5..0827f2cac 100644
--- a/xlators/features/changelog/lib/src/gf-changelog.c
+++ b/xlators/features/changelog/lib/src/gf-changelog.c
@@ -82,6 +82,10 @@ __attribute__ ((destructor)) gf_changelog_dtor (void)
gfc = this->private;
if (gfc) {
+ if (gfc->hist_gfc) {
+ gf_changelog_cleanup(gfc->hist_gfc);
+ GF_FREE (gfc->hist_gfc);
+ }
gf_changelog_cleanup (gfc);
GF_FREE (gfc);
}
@@ -437,6 +441,7 @@ gf_changelog_register (char *brick_path, char *scratch_dir,
int errn = 0;
xlator_t *this = NULL;
gf_changelog_t *gfc = NULL;
+ char hist_scratch_dir[PATH_MAX] = {0,};
this = THIS;
if (!this->ctx)
@@ -460,6 +465,52 @@ gf_changelog_register (char *brick_path, char *scratch_dir,
goto cleanup;
}
+ /* Begin: Changes for History API */
+ gfc->hist_gfc = NULL;
+
+ gfc->hist_gfc = GF_CALLOC (1, sizeof (*gfc),
+ gf_changelog_mt_libgfchangelog_t);
+ if (!gfc->hist_gfc)
+ goto cleanup;
+
+ gfc->hist_gfc->gfc_dir = NULL;
+ gfc->hist_gfc->gfc_fd = gfc->hist_gfc->gfc_sockfd = -1;
+ gfc->hist_gfc->this = NULL;
+
+ (void) strncpy (hist_scratch_dir, scratch_dir, PATH_MAX);
+ (void) snprintf (hist_scratch_dir, PATH_MAX,
+ "%s/"GF_CHANGELOG_HISTORY_DIR"/",
+ gfc->gfc_working_dir);
+
+ ret = mkdir_p (hist_scratch_dir, 0600, _gf_false);
+ if (ret) {
+ errn = errno;
+ goto cleanup;
+ }
+
+ gfc->hist_gfc->gfc_working_dir = realpath (hist_scratch_dir, NULL);
+ if (!gfc->hist_gfc->gfc_working_dir) {
+ errn = errno;
+ goto cleanup;
+ }
+
+ ret = gf_changelog_open_dirs (gfc->hist_gfc);
+ if (ret) {
+ errn = errno;
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not create entries in history scratch dir");
+ goto cleanup;
+ }
+
+ (void) strncpy (gfc->hist_gfc->gfc_brickpath, brick_path, PATH_MAX);
+
+ for (i=0; i < 256; i++) {
+ gfc->hist_gfc->rfc3986[i] =
+ (isalnum(i) || i == '~' ||
+ i == '-' || i == '.' || i == '_') ? i : 0;
+ }
+ /* End: Changes for History API*/
+
ret = gf_changelog_open_dirs (gfc);
if (ret) {
errn = errno;
@@ -494,7 +545,7 @@ gf_changelog_register (char *brick_path, char *scratch_dir,
goto cleanup;
}
- for (; i < 256; i++) {
+ for (i=0; i < 256; i++) {
gfc->rfc3986[i] =
(isalnum(i) || i == '~' ||
i == '-' || i == '.' || i == '_') ? i : 0;
@@ -506,6 +557,10 @@ gf_changelog_register (char *brick_path, char *scratch_dir,
goto out;
cleanup:
+ if (gfc->hist_gfc) {
+ gf_changelog_cleanup (gfc->hist_gfc);
+ GF_FREE (gfc->hist_gfc);
+ }
gf_changelog_cleanup (gfc);
GF_FREE (gfc);
this->private = NULL;
diff --git a/xlators/features/changelog/lib/src/gf-history-changelog.c b/xlators/features/changelog/lib/src/gf-history-changelog.c
new file mode 100644
index 000000000..bfc4cd37d
--- /dev/null
+++ b/xlators/features/changelog/lib/src/gf-history-changelog.c
@@ -0,0 +1,274 @@
+#include <errno.h>
+#include <dirent.h>
+#include <stddef.h>
+#include <sys/types.h>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <string.h>
+
+#include "globals.h"
+#include "glusterfs.h"
+#include "logging.h"
+
+#include "gf-changelog-helpers.h"
+
+/* from the changelog translator */
+#include "changelog-misc.h"
+#include "changelog-mem-types.h"
+
+/*@API
+ * gf_history_changelog_done:
+ * Move processed history changelog file from .processing
+ * to .processed
+ *
+ * ARGUMENTS:
+ * file(IN): path to processed history changelog file in
+ * .processing directory.
+ *
+ * RETURN VALUE:
+ * 0: On success.
+ * -1: On error.
+ */
+int
+gf_history_changelog_done (char *file)
+{
+ int ret = -1;
+ char *buffer = NULL;
+ xlator_t *this = NULL;
+ gf_changelog_t *gfc = NULL;
+ gf_changelog_t *hist_gfc = NULL;
+ char to_path[PATH_MAX] = {0,};
+
+ errno = EINVAL;
+
+ this = THIS;
+ if (!this)
+ goto out;
+
+ gfc = (gf_changelog_t *) this->private;
+ if (!gfc)
+ goto out;
+
+ hist_gfc = gfc->hist_gfc;
+ if (!hist_gfc)
+ goto out;
+
+ if (!file || !strlen (file))
+ goto out;
+
+ /* make sure 'file' is inside ->gfc_working_dir */
+ buffer = realpath (file, NULL);
+ if (!buffer)
+ goto out;
+
+ if (strncmp (hist_gfc->gfc_working_dir,
+ buffer, strlen (hist_gfc->gfc_working_dir)))
+ goto out;
+
+ (void) snprintf (to_path, PATH_MAX, "%s%s",
+ hist_gfc->gfc_processed_dir, basename (buffer));
+ gf_log (this->name, GF_LOG_DEBUG,
+ "moving %s to processed directory", file);
+ ret = rename (buffer, to_path);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "cannot move %s to %s (reason: %s)",
+ file, to_path, strerror (errno));
+ goto out;
+ }
+
+ ret = 0;
+
+ out:
+ if (buffer)
+ free (buffer); /* allocated by realpath() */
+ return ret;
+}
+/**
+ * @API
+ * gf_history_changelog_start_fresh:
+ * For a set of changelogs, start from the begining.
+ * It will truncates the history tracker fd.
+ *
+ * RETURN VALUES:
+ * 0: On success.
+ * -1: On error.
+ */
+int
+gf_history_changelog_start_fresh ()
+{
+ xlator_t *this = NULL;
+ gf_changelog_t *gfc = NULL;
+ gf_changelog_t *hist_gfc = NULL;
+
+ this = THIS;
+ if (!this)
+ goto out;
+
+ errno = EINVAL;
+
+ gfc = (gf_changelog_t *) this->private;
+ if (!gfc)
+ goto out;
+
+ hist_gfc = gfc->hist_gfc;
+ if (!hist_gfc)
+ goto out;
+
+ if (gf_ftruncate (hist_gfc->gfc_fd, 0))
+ goto out;
+
+ return 0;
+
+ out:
+ return -1;
+}
+
+/*
+ * @API
+ * gf_history_changelog_next_change:
+ * Return the next history changelog file entry. Zero means all
+ * history chanelogs are consumed.
+ *
+ * ARGUMENTS:
+ * bufptr(OUT): Path to unprocessed history changelog file
+ * from tracker file.
+ * maxlen(IN): Usually PATH_MAX.
+ *
+ * RETURN VALUES:
+ * size: On success.
+ * -1 : On error.
+ */
+ssize_t
+gf_history_changelog_next_change (char *bufptr, size_t maxlen)
+{
+ ssize_t size = 0;
+ int tracker_fd = 0;
+ xlator_t *this = NULL;
+ gf_changelog_t *gfc = NULL;
+ gf_changelog_t *hist_gfc = NULL;
+ char buffer[PATH_MAX] = {0,};
+
+ errno = EINVAL;
+
+ this = THIS;
+ if (!this)
+ goto out;
+
+ gfc = (gf_changelog_t *) this->private;
+ if (!gfc)
+ goto out;
+
+ hist_gfc = gfc->hist_gfc;
+ if (!hist_gfc)
+ goto out;
+
+ tracker_fd = hist_gfc->gfc_fd;
+
+ size = gf_readline (tracker_fd, buffer, maxlen);
+ if (size < 0)
+ goto out;
+ if (size == 0)
+ return 0;
+
+ memcpy (bufptr, buffer, size - 1);
+ *(buffer + size) = '\0';
+
+ return size;
+
+ out:
+ return -1;
+}
+
+/*
+ * @API
+ * gf_history_changelog_scan:
+ * Scan and generate a list of change entries.
+ * Calling this api multiple times (without calling gf_changlog_done())
+ * would result new changelogs(s) being refreshed in the tracker file.
+ * This call also acts as a cancellation point for the consumer.
+ *
+ * RETURN VALUES:
+ * nr_entries: On success.
+ * -1 : On error.
+ */
+ssize_t
+gf_history_changelog_scan ()
+{
+ int ret = 0;
+ int tracker_fd = 0;
+ size_t len = 0;
+ size_t off = 0;
+ xlator_t *this = NULL;
+ size_t nr_entries = 0;
+ gf_changelog_t *gfc = NULL;
+ gf_changelog_t *hist_gfc = NULL;
+ struct dirent *entryp = NULL;
+ struct dirent *result = NULL;
+ char buffer[PATH_MAX] = {0,};
+
+ this = THIS;
+ if (!this)
+ goto out;
+
+ gfc = (gf_changelog_t *) this->private;
+ if (!gfc)
+ goto out;
+
+ hist_gfc = gfc->hist_gfc;
+ if (!hist_gfc)
+ goto out;
+
+ errno = EINVAL;
+
+ tracker_fd = hist_gfc->gfc_fd;
+
+ if (gf_ftruncate (tracker_fd, 0))
+ goto out;
+
+ len = offsetof(struct dirent, d_name)
+ + pathconf(hist_gfc->gfc_processing_dir, _PC_NAME_MAX) + 1;
+ entryp = GF_CALLOC (1, len,
+ gf_changelog_mt_libgfchangelog_dirent_t);
+ if (!entryp)
+ goto out;
+
+ rewinddir (hist_gfc->gfc_dir);
+ while (1) {
+ ret = readdir_r (hist_gfc->gfc_dir, entryp, &result);
+ if (ret || !result)
+ break;
+
+ if ( !strcmp (basename (entryp->d_name), ".")
+ || !strcmp (basename (entryp->d_name), "..") )
+ continue;
+
+ nr_entries++;
+
+ GF_CHANGELOG_FILL_BUFFER (hist_gfc->gfc_processing_dir,
+ buffer, off,
+ strlen (hist_gfc->gfc_processing_dir));
+ GF_CHANGELOG_FILL_BUFFER (entryp->d_name, buffer,
+ off, strlen (entryp->d_name));
+ GF_CHANGELOG_FILL_BUFFER ("\n", buffer, off, 1);
+
+ if (gf_changelog_write (tracker_fd, buffer, off) != off) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "error writing changelog filename"
+ " to tracker file");
+ break;
+ }
+ off = 0;
+ }
+
+ GF_FREE (entryp);
+
+ if (!result) {
+ if (gf_lseek (tracker_fd, 0, SEEK_SET) != -1)
+ return nr_entries;
+ }
+ out:
+ return -1;
+}
diff --git a/xlators/features/changelog/src/Makefile.am b/xlators/features/changelog/src/Makefile.am
index d802584df..525ce97dc 100644
--- a/xlators/features/changelog/src/Makefile.am
+++ b/xlators/features/changelog/src/Makefile.am
@@ -14,7 +14,7 @@ changelog_la_SOURCES = changelog.c changelog-rt.c changelog-helpers.c \
changelog_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -Ipolicy/ -fPIC -D_FILE_OFFSET_BITS=64 \
- -D_GNU_SOURCE -D$(GF_HOST_OS) -shared -nostartfiles -DDATADIR=\"$(localstatedir)\"
+ -D_GNU_SOURCE -D$(GF_HOST_OS) -shared -DDATADIR=\"$(localstatedir)\"
AM_CFLAGS = -Wall $(GF_CFLAGS)
diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h
index f8f254cf6..e4e2dfc96 100644
--- a/xlators/features/changelog/src/changelog-helpers.h
+++ b/xlators/features/changelog/src/changelog-helpers.h
@@ -422,9 +422,11 @@ typedef struct {
void
changelog_thread_cleanup (xlator_t *this, pthread_t thr_id);
-inline void *
+
+void *
changelog_get_usable_buffer (changelog_local_t *local);
-inline void
+
+void
changelog_set_usable_record_and_length (changelog_local_t *local,
size_t len, int xr);
void
@@ -437,9 +439,9 @@ changelog_inject_single_event (xlator_t *this,
changelog_priv_t *priv,
changelog_local_t *local,
changelog_log_data_t *cld);
-inline size_t
+size_t
changelog_entry_length ();
-inline int
+int
changelog_write (int fd, char *buffer, size_t len);
int
changelog_write_change (xlator_t *this, changelog_priv_t *priv,
diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c
index 66fdd61be..6d4b502de 100644
--- a/xlators/features/changelog/src/changelog.c
+++ b/xlators/features/changelog/src/changelog.c
@@ -1370,12 +1370,11 @@ struct volume_options options[] = {
.description = "encoding type for changelogs"
},
{.key = {"rollover-time"},
- .type = GF_OPTION_TYPE_INT,
.description = "time to switch to a new changelog file (in seconds)"
},
{.key = {"fsync-interval"},
.type = GF_OPTION_TYPE_TIME,
- .default_value = "0",
+ .default_value = "5",
.description = "do not open CHANGELOG file with O_SYNC mode."
" instead perform fsync() at specified intervals"
},