/* Copyright (c) 2013 Red Hat, Inc. This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" #endif #include "changelog-encoders.h" size_t entry_fn (void *data, char *buffer, gf_boolean_t encode) { char *tmpbuf = NULL; size_t bufsz = 0; struct changelog_entry_fields *ce = NULL; ce = (struct changelog_entry_fields *) data; if (encode) { tmpbuf = uuid_utoa (ce->cef_uuid); CHANGELOG_FILL_BUFFER (buffer, bufsz, tmpbuf, strlen (tmpbuf)); } else { CHANGELOG_FILL_BUFFER (buffer, bufsz, ce->cef_uuid, sizeof (uuid_t)); } CHANGELOG_FILL_BUFFER (buffer, bufsz, "/", 1); CHANGELOG_FILL_BUFFER (buffer, bufsz, ce->cef_bname, strlen (ce->cef_bname)); return bufsz; } size_t del_entry_fn (void *data, char *buffer, gf_boolean_t encode) { char *tmpbuf = NULL; size_t bufsz = 0; struct changelog_entry_fields *ce = NULL; ce = (struct changelog_entry_fields *) data; if (encode) { tmpbuf = uuid_utoa (ce->cef_uuid); CHANGELOG_FILL_BUFFER (buffer, bufsz, tmpbuf, strlen (tmpbuf)); } else { CHANGELOG_FILL_BUFFER (buffer, bufsz, ce->cef_uuid, sizeof (uuid_t)); } CHANGELOG_FILL_BUFFER (buffer, bufsz, "/", 1); CHANGELOG_FILL_BUFFER (buffer, bufsz, ce->cef_bname, strlen (ce->cef_bname)); CHANGELOG_FILL_BUFFER (buffer, bufsz, "\0", 1); if (ce->cef_path[0] == '\0') { CHANGELOG_FILL_BUFFER (buffer, bufsz, "\0", 1); } else { CHANGELOG_FILL_BUFFER (buffer, bufsz, ce->cef_path, strlen (ce->cef_path)); } return bufsz; } size_t fop_fn (void *data, char *buffer, gf_boolean_t encode) { char buf[10] = {0,}; size_t bufsz = 0; glusterfs_fop_t fop = 0; fop = *(glusterfs_fop_t *) data; if (encode) { (void) snprintf (buf, sizeof (buf), "%d", fop); CHANGELOG_FILL_BUFFER (buffer, bufsz, buf, strlen (buf)); } else CHANGELOG_FILL_BUFFER (buffer, bufsz, &fop, sizeof (fop)); return bufsz; } size_t number_fn (void *data, char *buffer, gf_boolean_t encode) { size_t bufsz = 0; unsigned int nr = 0; char buf[20] = {0,}; nr = *(unsigned int *) data; if (encode) { (void) snprintf (buf, sizeof (buf), "%u", nr); CHANGELOG_FILL_BUFFER (buffer, bufsz, buf, strlen (buf)); } else CHANGELOG_FILL_BUFFER (buffer, bufsz, &nr, sizeof (unsigned int)); return bufsz; } void entry_free_fn (void *data) { changelog_opt_t *co = data; if (!co) return; GF_FREE (co->co_entry.cef_bname); } void del_entry_free_fn (void *data) { changelog_opt_t *co = data; if (!co) return; GF_FREE (co->co_entry.cef_bname); GF_FREE (co->co_entry.cef_path); } /** * try to write all data in one shot */ static void changelog_encode_write_xtra (changelog_log_data_t *cld, char *buffer, size_t *off, gf_boolean_t encode) { int i = 0; size_t offset = 0; void *data = NULL; changelog_opt_t *co = NULL; offset = *off; co = (changelog_opt_t *) cld->cld_ptr; for (; i < cld->cld_xtra_records; i++, co++) { CHANGELOG_FILL_BUFFER (buffer, offset, "\0", 1); switch (co->co_type) { case CHANGELOG_OPT_REC_FOP: data = &co->co_fop; break; case CHANGELOG_OPT_REC_ENTRY: data = &co->co_entry; break; case CHANGELOG_OPT_REC_UINT32: data = &co->co_uint32; break; } if (co->co_convert) offset += co->co_convert (data, buffer + offset, encode); else /* no coversion: write it out as it is */ CHANGELOG_FILL_BUFFER (buffer, offset, data, co->co_len); } *off = offset; } int changelog_encode_ascii (xlator_t *this, changelog_log_data_t *cld) { size_t off = 0; size_t gfid_len = 0; char *gfid_str = NULL; char *buffer = NULL; changelog_priv_t *priv = NULL; priv = this->private; gfid_str = uuid_utoa (cld->cld_gfid); gfid_len = strlen (gfid_str); /* extra bytes for decorations */ buffer = alloca (gfid_len + cld->cld_ptr_len + 10); CHANGELOG_STORE_ASCII (priv, buffer, off, gfid_str, gfid_len, cld); if (cld->cld_xtra_records) changelog_encode_write_xtra (cld, buffer, &off, _gf_true); CHANGELOG_FILL_BUFFER (buffer, off, "\0", 1); return changelog_write_change (priv, buffer, off); } int changelog_encode_binary (xlator_t *this, changelog_log_data_t *cld) { size_t off = 0; char *buffer = NULL; changelog_priv_t *priv = NULL; priv = this->private; /* extra bytes for decorations */ buffer = alloca (sizeof (uuid_t) + cld->cld_ptr_len + 10); CHANGELOG_STORE_BINARY (priv, buffer, off, cld->cld_gfid, cld); if (cld->cld_xtra_records) changelog_encode_write_xtra (cld, buffer, &off, _gf_false); CHANGELOG_FILL_BUFFER (buffer, off, "\0", 1); return changelog_write_change (priv, buffer, off); } static struct changelog_encoder cb_encoder[] = { [CHANGELOG_ENCODE_BINARY] = { .encoder = CHANGELOG_ENCODE_BINARY, .encode = changelog_encode_binary, }, [CHANGELOG_ENCODE_ASCII] = { .encoder = CHANGELOG_ENCODE_ASCII, .encode = changelog_encode_ascii, }, }; void changelog_encode_change(changelog_priv_t *priv) { priv->ce = &cb_encoder[priv->encode_mode]; }