diff options
Diffstat (limited to 'xlators/features/changelog/src/changelog-helpers.h')
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.h | 279 |
1 files changed, 225 insertions, 54 deletions
diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index 53588f55e..e4e2dfc96 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; @@ -281,29 +435,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); size_t changelog_entry_length (); int changelog_write (int fd, char *buffer, size_t len); int -changelog_write_change (changelog_priv_t *priv, char *buffer, size_t len); -int +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); -void -changelog_update (xlator_t *this, changelog_priv_t *priv, - changelog_local_t *local, changelog_log_type type); + 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); void * changelog_rollover (void *data); void * @@ -323,9 +474,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 { \ @@ -350,22 +498,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 { \ @@ -404,4 +572,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 */ |