summaryrefslogtreecommitdiffstats
path: root/xlators/features/changelog/src/changelog-helpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/changelog/src/changelog-helpers.h')
-rw-r--r--xlators/features/changelog/src/changelog-helpers.h275
1 files changed, 223 insertions, 52 deletions
diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h
index b441f7068..f8f254cf6 100644
--- a/xlators/features/changelog/src/changelog-helpers.h
+++ b/xlators/features/changelog/src/changelog-helpers.h
@@ -19,23 +19,15 @@
#include "changelog-misc.h"
/**
- * the changelog entry
+ * structures representing the changelog entries
*/
-typedef struct changelog_log_data {
- /* rollover related */
- unsigned long cld_roll_time;
-
- /* reopen changelog? */
- gf_boolean_t cld_finale;
-
- changelog_log_type cld_type;
-
+typedef struct changelog_write_data {
/**
* sincd gfid is _always_ a necessity, it's not a part
* of the iobuf. by doing this we do not add any overhead
* for data and metadata related fops.
*/
- uuid_t cld_gfid;
+ uuid_t cwd_gfid;
/**
* iobufs are used for optionals records: pargfid, path,
@@ -43,25 +35,78 @@ typedef struct changelog_log_data {
* to allocate (iobuf_get() in the fop) and get unref'ed
* in the callback (CHANGELOG_STACK_UNWIND).
*/
- struct iobuf *cld_iobuf;
-
-#define cld_ptr cld_iobuf->ptr
+ struct iobuf *cwd_iobuf;
/**
* after allocation you can point this to the length of
* usable data, but make sure it does not exceed the
* the size of the requested iobuf.
*/
- size_t cld_iobuf_len;
-
-#define cld_ptr_len cld_iobuf_len
+ size_t cwd_iobuf_len;
+ #define cwd_ptr cwd_iobuf->ptr
+ #define cwd_ptr_len cwd_iobuf_len
/**
* number of optional records
*/
- int cld_xtra_records;
+ int cwd_xtra_records;
+} changelog_write_data_t;
+
+typedef struct changelog_rollover_data {
+ /**
+ * need a changelog reopen?
+ */
+ gf_boolean_t crd_finale;
+
+ /**
+ * changelog file name to be opened after a rollover
+ */
+ char crd_changelog_name[PATH_MAX];
+
+ /**
+ * changelog file name before rollover
+ */
+ char crd_changelog_oname[PATH_MAX];
+
+ /**
+ * use @crd_roll_key as suffix during roll-over
+ */
+ gf_boolean_t crd_use_suffix;
+
+ /**
+ * suffix used when rolling a changelog
+ */
+ unsigned long crd_roll_key;
+
+ /**
+ * preallocation? if yes, how much?
+ */
+ off_t crd_prealloc_size;
+} changelog_rollover_data_t;
+
+/**
+ * the changelog entry: structure representing the type of entry
+ * and a union encapsulating the above declared structures.
+ */
+typedef struct changelog_log_data {
+ /**
+ * type of the log data entry
+ */
+ changelog_log_type cld_type;
+
+ /**
+ * union for the type of changelog operations. @fsync() does
+ * not have a corresponding entry in this union as it just
+ * performs and @fsync() on ->changelog_fd.
+ */
+ union {
+ changelog_write_data_t cld_wdata;
+ changelog_rollover_data_t cld_roll;
+ };
} changelog_log_data_t;
+typedef struct changelog_local changelog_local_t;
+
/**
* holder for dispatch function and private data
*/
@@ -70,21 +115,97 @@ typedef struct changelog_priv changelog_priv_t;
typedef struct changelog_dispatcher {
void *cd_data;
- int (*dispatchfn) (xlator_t *, changelog_priv_t *, void *,
- changelog_log_data_t *, changelog_log_data_t *);
+ int (*dispatchfn) (xlator_t *,
+ changelog_priv_t *, void *,
+ changelog_local_t *, changelog_log_data_t *);
} changelog_dispatcher_t;
struct changelog_bootstrap {
changelog_mode_t mode;
- int (*ctor) (xlator_t *, changelog_dispatcher_t *);
+ int (*ctor) (xlator_t *, changelog_dispatcher_t *, gf_boolean_t);
int (*dtor) (xlator_t *, changelog_dispatcher_t *);
};
struct changelog_encoder {
changelog_encoder_t encoder;
- int (*encode) (xlator_t *, changelog_log_data_t *);
+ int (*encode) (xlator_t *,
+ changelog_local_t *, changelog_log_data_t *);
};
+struct changelog_ops {
+ /* changelog open */
+ int (*open) (xlator_t *, changelog_priv_t *,
+ void *, char *, gf_boolean_t);
+
+ /* changelog close */
+ int (*close) (xlator_t *, changelog_priv_t *, void *);
+
+ /* changelog rollover */
+ int (*rollover) (xlator_t *,
+ changelog_priv_t *,
+ void *, char *, gf_boolean_t);
+
+ int (*sync) (xlator_t *, changelog_priv_t *, void *);
+
+ /* changelog write */
+ int (*write) (xlator_t *,
+ changelog_priv_t *, void *,
+ changelog_local_t *, changelog_log_type);
+
+ /* changelog read */
+ int (*read) (xlator_t *,
+ changelog_priv_t *, void *, char *);
+
+ int (*unlink) (xlator_t *,
+ changelog_priv_t *, void *, char *);
+
+ /* {get|set} offset */
+ off_t (*get_offset) (xlator_t *this,
+ changelog_priv_t *, void *, changelog_local_t *);
+
+ void (*set_offset) (xlator_t *this,
+ changelog_priv_t *, void *,
+ changelog_local_t *, off_t);
+
+ void (*reset_offset) (xlator_t *this, changelog_priv_t *,
+ void *, changelog_local_t *);
+};
+
+/**
+ * This structure is _filled_ by the policy init (@init_policy) routine.
+ * Default @fops and @cops are passed to the init routine, which can
+ * choose to override the file operation or changelog operation behaviour.
+ * Just by _replacing_ the function pointers, a policy can change it's
+ * file and changelog operation behaviour. Kind of inheritance...
+ */
+struct changelog_logpolicy {
+ /* current changelog name */
+ char changelog_name[PATH_MAX];
+
+ /* private data */
+ void *cpriv;
+
+ /* file ops for the policy */
+ struct xlator_fops *fops;
+
+ /* changelog operations for the policy */
+ struct changelog_ops *cops;
+
+ /* current active policy */
+ changelog_log_policy_t policy;
+
+ int (*init_policy) (xlator_t *,
+ changelog_priv_t *priv,
+ struct changelog_logpolicy *);
+ int (*fini_policy) (xlator_t *, struct changelog_logpolicy *);
+};
+
+#define CHANGELOG_FNAME_FROM_POLICY(c) c->changelog_name
+
+#define CHANGELOG_INVOKE_FOP(priv,fop,...) priv->cp->fops->fop (__VA_ARGS__)
+
+#define CHANGELOG_INVOKE_CFOP(this,priv,fop,...) \
+ priv->cp->cops->fop (this, priv, priv->cp->cpriv, ##__VA_ARGS__)
/* xlator private */
@@ -142,6 +263,13 @@ typedef struct changelog_notify {
struct changelog_priv {
gf_boolean_t active;
+ /**
+ * write the record header?
+ */
+ gf_boolean_t no_gfid_hdr;
+
+ gf_boolean_t lockless_update;
+
/* to generate unique socket file per brick */
char *changelog_brick;
@@ -191,24 +319,43 @@ struct changelog_priv {
/* encoder */
struct changelog_encoder *ce;
+
+ /* logging policy */
+ changelog_log_policy_t policy;
+
+ /* policy logger */
+ struct changelog_logpolicy *cp;
+
+ /* current NSR term */
+ uint32_t term;
};
struct changelog_local {
inode_t *inode;
+
+ /**
+ * fops that do not need inode version checks
+ */
gf_boolean_t update_no_check;
+ /**
+ * the log data entry
+ */
changelog_log_data_t cld;
/**
- * ->prev_entry is used in cases when there needs to be
- * additional changelog entry for the parent (eg. rename)
- * It's analogous to ->next in single linked list world,
- * but we call it as ->prev_entry... ha ha ha
+ * number of bytes written: used for continuation
*/
- struct changelog_local *prev_entry;
-};
+ off_t nr_bytes;
-typedef struct changelog_local changelog_local_t;
+ /**
+ * temporary scratch pads
+ */
+ union {
+ void *ptr;
+ unsigned long val;
+ } lu;
+};
/* inode version is stored in inode ctx */
typedef struct changelog_inode_ctx {
@@ -224,7 +371,11 @@ typedef struct changelog_inode_ctx {
*/
typedef enum {
CHANGELOG_OPT_REC_FOP,
+ CHANGELOG_OPT_REC_ULL,
+ CHANGELOG_OPT_REC_UUID,
+ CHANGELOG_OPT_REC_NAME,
CHANGELOG_OPT_REC_ENTRY,
+ CHANGELOG_OPT_REC_INT32,
CHANGELOG_OPT_REC_UINT32,
} changelog_optional_rec_type_t;
@@ -254,8 +405,11 @@ typedef struct {
size_t co_len;
union {
- unsigned int co_uint32;
+ uuid_t co_uuid;
glusterfs_fop_t co_fop;
+ int co_int32;
+ unsigned int co_uint32;
+ unsigned long long co_number;
struct changelog_entry_fields co_entry;
};
} changelog_opt_t;
@@ -279,29 +433,26 @@ changelog_local_t *
changelog_local_init (xlator_t *this, inode_t *inode, uuid_t gfid,
int xtra_records, gf_boolean_t update_flag);
int
-changelog_start_next_change (xlator_t *this,
- changelog_priv_t *priv,
- unsigned long ts, gf_boolean_t finale);
-int
-changelog_open (xlator_t *this, changelog_priv_t *priv);
-int
-changelog_fill_rollover_data (changelog_log_data_t *cld, gf_boolean_t is_last);
-int
changelog_inject_single_event (xlator_t *this,
changelog_priv_t *priv,
+ changelog_local_t *local,
changelog_log_data_t *cld);
inline size_t
changelog_entry_length ();
inline int
changelog_write (int fd, char *buffer, size_t len);
int
-changelog_write_change (changelog_priv_t *priv, char *buffer, size_t len);
+changelog_write_change (xlator_t *this, changelog_priv_t *priv,
+ changelog_local_t *local, char *buffer, size_t len);
inline int
changelog_handle_change (xlator_t *this,
- changelog_priv_t *priv, changelog_log_data_t *cld);
+ changelog_priv_t *priv,
+ changelog_local_t *local, changelog_log_data_t *cld);
inline void
-changelog_update (xlator_t *this, changelog_priv_t *priv,
- changelog_local_t *local, changelog_log_type type);
+changelog_update (xlator_t *this,
+ changelog_priv_t *priv,
+ changelog_local_t *local,
+ changelog_log_type type);
void *
changelog_rollover (void *data);
void *
@@ -321,9 +472,6 @@ changelog_forget (xlator_t *this, inode_t *inode);
} \
STACK_UNWIND_STRICT (fop, frame, params); \
changelog_local_cleanup (__xl, __local); \
- if (__local && __local->prev_entry) \
- changelog_local_cleanup (__xl, \
- __local->prev_entry); \
} while (0)
#define CHANGELOG_IOBUF_REF(iobuf) do { \
@@ -348,22 +496,42 @@ changelog_forget (xlator_t *this, inode_t *inode);
} \
} while (0)
+#define CHANGELOG_FILL_INT32(co, number, converter, xlen) do { \
+ co->co_convert = converter; \
+ co->co_free = NULL; \
+ co->co_type = CHANGELOG_OPT_REC_INT32; \
+ co->co_int32 = number; \
+ xlen += sizeof (int); \
+ } while (0)
+
#define CHANGELOG_FILL_UINT32(co, number, converter, xlen) do { \
co->co_convert = converter; \
co->co_free = NULL; \
co->co_type = CHANGELOG_OPT_REC_UINT32; \
co->co_uint32 = number; \
- xlen += sizeof (unsigned int); \
+ xlen += sizeof (unsigned int); \
} while (0)
-#define CHANGLOG_FILL_FOP_NUMBER(co, fop, converter, xlen) do { \
- co->co_convert = converter; \
- co->co_free = NULL; \
- co->co_type = CHANGELOG_OPT_REC_FOP; \
- co->co_fop = fop; \
- xlen += sizeof (fop); \
+#define CHANGELOG_FILL_FOP_NUMBER(co, fop, converter, xlen) do { \
+ co->co_convert = converter; \
+ co->co_free = NULL; \
+ co->co_type = CHANGELOG_OPT_REC_FOP; \
+ co->co_fop = fop; \
+ xlen += sizeof (fop); \
} while (0)
+#define CHANGELOG_FILL_NAME(co, name, freefn, xlen, label) \
+ do { \
+ co->co_convert = NULL; \
+ co->co_free = freefn; \
+ co->co_type = CHANGELOG_OPT_REC_NAME; \
+ co->co_entry.cef_bname = gf_strdup(name); \
+ if (!co->co_entry.cef_bname) \
+ goto label; \
+ co->co_len = strlen (name); \
+ xlen += co->co_len; \
+ } while(0) \
+
#define CHANGELOG_FILL_ENTRY(co, pargfid, bname, \
converter, freefn, xlen, label) \
do { \
@@ -402,4 +570,7 @@ changelog_forget (xlator_t *this, inode_t *inode);
goto label; \
} while (0)
+int
+changelog_open (xlator_t *this, changelog_priv_t *priv, changelog_local_t *local, changelog_rollover_data_t *crd);
+
#endif /* _CHANGELOG_HELPERS_H */