diff options
| author | Kaushik BV <kaushikbv@gluster.com> | 2011-01-27 05:23:30 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2011-01-27 03:16:51 -0800 | 
| commit | 73bce15b61755509de23d32646135254d369a2f6 (patch) | |
| tree | 921b92f6d3e549b1e6dd68bc886cc727caec5429 /xlators/lib/src | |
| parent | 11dd59b788334fe2de1653ae85395986ba531606 (diff) | |
adding libxlator, to ensure proper client side aggregation of marks by clustering translators
Signed-off-by: Kaushik BV <kaushikbv@gluster.com>
Signed-off-by: Csaba Henk <csaba@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 2310 (georeplication)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2310
Diffstat (limited to 'xlators/lib/src')
| -rw-r--r-- | xlators/lib/src/libxlator.c | 371 | ||||
| -rw-r--r-- | xlators/lib/src/libxlator.h | 86 | 
2 files changed, 457 insertions, 0 deletions
diff --git a/xlators/lib/src/libxlator.c b/xlators/lib/src/libxlator.c new file mode 100644 index 00000000000..7708f86e619 --- /dev/null +++ b/xlators/lib/src/libxlator.c @@ -0,0 +1,371 @@ +#include "mem-types.h" +#include "libxlator.h" + + +/*Copy the contents of oldtimebuf to newtimbuf*/ +static void +update_timebuf (uint32_t *oldtimbuf, uint32_t *newtimebuf) +{ +        newtimebuf[0] =  (oldtimbuf[0]); +        newtimebuf[1] =  (oldtimbuf[1]); +} + +/* Convert Timebuf in network order to host order */ +static void +get_hosttime (uint32_t *oldtimbuf, uint32_t *newtimebuf) +{ +        newtimebuf[0] = ntohl (oldtimbuf[0]); +        newtimebuf[1] = ntohl (oldtimbuf[1]); +} + + + +/* Match the Incoming trusted.glusterfs.<uuid>.xtime against volume uuid */ +int +match_uuid_local (const char *name, char *uuid) +{ +        name = strtail ((char *)name, MARKER_XATTR_PREFIX); +        if (!name || name++[0] != '.') +                return -1; + +        name = strtail ((char *)name, uuid); +        if (!name || strcmp (name, ".xtime") != 0) +                return -1; + +        return 0; +} + + + + +/* Aggregate all the <volid>.xtime attrs of the cluster and send the max*/ +int32_t +cluster_markerxtime_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int op_ret, int op_errno, dict_t *dict) + +{ + +        int32_t            callcnt = 0; +        int                ret = -1; +        uint32_t          *net_timebuf; +        uint32_t           host_timebuf[2]; +        char              *marker_xattr; +        struct marker_str *local; +        char              *vol_uuid; + +        if (!this || !frame || !frame->local || !cookie) { +                gf_log (this->name, GF_LOG_DEBUG, "possible NULL deref"); +                goto out; +        } + +        local = frame->local; +        if (!local || !local->vol_uuid) { +                gf_log (this->name, GF_LOG_DEBUG, "possible NULL deref"); +                goto out; +        } + +        vol_uuid = local->vol_uuid; + +        if (op_ret && op_errno == ENOENT) { +                LOCK (&frame->lock); +                { +                        callcnt = --local->call_count; +                        local->enoent_count++; +                } +                goto done; +        } + +        if (op_ret && op_errno == ENOTCONN) { +                LOCK (&frame->lock); +                { +                        callcnt = --local->call_count; +                        local->enotconn_count++; +                } +                goto done; +        } + + +        LOCK (&frame->lock); +        { +                callcnt = --local->call_count; +                if (!gf_asprintf (& marker_xattr, "%s.%s.%s", +                                MARKER_XATTR_PREFIX, vol_uuid, XTIME)) { +                        op_errno = ENOMEM; +                        goto out; +                } + + +                if (dict_get_ptr (dict, marker_xattr, (void **)&net_timebuf)) { +                        gf_log (this->name, GF_LOG_WARNING, +                                "Unable to get <uuid>.xtime attr"); + +                        goto done; +                } + +                if (local->has_xtime) { + +                        get_hosttime (net_timebuf, host_timebuf); +                        if ( (host_timebuf[0]>local->host_timebuf[0]) || +                                (host_timebuf[0] == local->host_timebuf[0] && +                                 host_timebuf[1] >= local->host_timebuf[1])) { + +                                update_timebuf (net_timebuf, local->net_timebuf); +                                update_timebuf (host_timebuf, local->host_timebuf); + +                        } + +                } +                else { +                        get_hosttime (net_timebuf, local->host_timebuf); +                        update_timebuf (net_timebuf, local->net_timebuf); +                        local->has_xtime = _gf_true; +                } + + + +        } +done: +        UNLOCK (&frame->lock); + +        if (!callcnt) { + +                op_ret = 0; +                op_errno = 0; +                if (local->has_xtime) { +                        if (!dict) { +                                dict = dict_new(); +                                if (ret) { +                                        op_ret = -1; +                                        op_errno = ENOMEM; +                                        goto out; +                                } +                        } +                        ret = dict_set_static_bin (dict, marker_xattr, +                                           (void *)local->net_timebuf, 8); +                        if (ret) { +                                op_ret = -1; +                                op_errno = ENOMEM; +                                goto out; +                        } +                } +                else { +                        op_ret = -1; +                        if (local->enotconn_count) { +                                op_errno = ENOTCONN; +                                goto out; +                        } +                        if (local->enoent_count) { +                                op_errno = ENOENT; +                                goto out; +                        } +                        else { +                                op_errno = EINVAL; +                                goto out; +                        } +                } +out: +                if (local->xl_specf_unwind) { +                        frame->local = local->xl_local; +                        local->xl_specf_unwind (getxattr, frame, op_ret, +                                                 op_errno, dict); +                        return 0; +                } +                STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + +        } + +        return 0; + +} + +int32_t +cluster_markeruuid_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int op_ret, int op_errno, dict_t *dict) +{ +        int32_t              callcnt = 0; +        data_t              *data = NULL; +        struct volume_mark  *volmark = NULL; +        struct marker_str   *marker = NULL; +        char                *vol_uuid; + + +        if (!this || !frame || !cookie) { +                gf_log (this->name, GF_LOG_DEBUG, "possible NULL deref"); +                goto out; +        } + +        marker = frame->local; + +        if (!marker) { +                gf_log (this->name, GF_LOG_DEBUG, "possible NULL deref"); +                goto out; +        } + +        vol_uuid = marker->vol_uuid; + +        if (op_ret && (ENOENT == op_errno)) { +                LOCK (&frame->lock); +                { +                        callcnt = --marker->call_count; +                        marker->enoent_count++; +                } +                goto done; +        } + +        if (op_ret && (ENOTCONN == op_errno)) { +                LOCK (&frame->lock); +                { +                        callcnt = --marker->call_count; +                        marker->enotconn_count++; +                } +                goto done; +        } + +        if (!(data = dict_get (dict, GF_XATTR_MARKER_KEY))) { +                LOCK (&frame->lock); +                { +                        callcnt = --marker->call_count; +                } +                goto done; +        } + +        volmark = (struct volume_mark *)data->data; + +        LOCK (&frame->lock); +        { +                callcnt = --marker->call_count; + +                if (marker_has_volinfo (marker)) { + +                        if ((marker->volmark->major != volmark->major) || +                            (marker->volmark->minor != volmark->minor)) { +                                op_ret = -1; +                                op_errno = EINVAL; +                                goto out; +                        } +                        else if (volmark->retval) { +                                data_unref ((data_t *) marker->volmark); +                                marker->volmark = volmark; +                                callcnt = 0; +                        } +                        else if ( (volmark->sec > marker->volmark->sec) || +                                   ((volmark->sec == marker->volmark->sec) +                                      && (volmark->usec >= marker->volmark->usec))) { + +                                marker->volmark = volmark; +                        } + +                } else { +                        marker->volmark = volmark; +                        uuid_unparse (volmark->uuid, vol_uuid); +                        if (volmark->retval) +                                callcnt = 0; +                } +        } +done: +        UNLOCK (&frame->lock); + +        if (!callcnt) { +                op_ret = 0; +                op_errno = 0; +                if (marker_has_volinfo (marker)) { +                        if (!dict) { +                                dict = dict_new(); +                                if (!dict) { +                                        op_ret = -1; +                                        op_errno = ENOMEM; +                                        goto out; +                                } +                        } +                        if (dict_set_static_bin (dict, GF_XATTR_MARKER_KEY, +                                          marker->volmark, +                                          sizeof (struct volume_mark))) { +                                op_ret = -1; +                                op_errno = ENOMEM; +                        } +                        goto out; +                } +                if (marker->enotconn_count) { +                        op_ret = -1; +                        op_errno = ENOTCONN; +                        goto out; +                } +                if (marker->enoent_count) { +                        op_ret = -1; +                        op_errno = ENOENT; +                } +                else { +                        op_ret = -1; +                        op_errno = EINVAL; +                } + + out: +                if (marker->xl_specf_unwind) { +                        frame->local = marker->xl_local; +                        marker->xl_specf_unwind (getxattr, frame, op_ret, +                                                 op_errno, dict); +                        return 0; +                } +                STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); +        } +        return 0; +} + + +int32_t +cluster_getmarkerattr (call_frame_t *frame,xlator_t *this, loc_t *loc, +                       const char *name, void *xl_local, +                       xlator_specf_unwind_t xl_specf_getxattr_unwind, +                       xlator_t **sub_volumes, int count, int type, +                       char *vol_uuid) +{ +        int               i; +        struct marker_str *local; + +        VALIDATE_OR_GOTO (frame, err); +        VALIDATE_OR_GOTO (this, err); +        VALIDATE_OR_GOTO (loc, err); +        VALIDATE_OR_GOTO (loc->path, err); +        VALIDATE_OR_GOTO (loc->inode, err); +        VALIDATE_OR_GOTO (name, err); +        VALIDATE_OR_GOTO (xl_specf_getxattr_unwind, err); + +        local = GF_CALLOC (sizeof (struct marker_str), 1, +                            gf_common_mt_libxl_marker_local); + +        local->xl_local = xl_local; +        frame->local = local; + +        local->call_count = count; + +        local->xl_specf_unwind = xl_specf_getxattr_unwind; + +        local->vol_uuid = vol_uuid; + +        for (i=0; i < count; i++) { +                if (MARKER_UUID_TYPE == type) +                        STACK_WIND (frame, cluster_markeruuid_cbk, +                                    *(sub_volumes + i), +                                    (*(sub_volumes + i))->fops->getxattr, +                                    loc, name); +                else if (MARKER_XTIME_TYPE == type) +                        STACK_WIND (frame, cluster_markerxtime_cbk, +                                    *(sub_volumes + i), +                                    (*(sub_volumes + i))->fops->getxattr, +                                    loc, name); +                else { +                        gf_log (this->name, GF_LOG_WARNING, +                                 "Unrecognized type of marker attr recived"); +                        STACK_WIND (frame, default_getxattr_cbk, +                                    *(sub_volumes + i), +                                    (*(sub_volumes + i))->fops->getxattr, +                                    loc, name); +                        break; +                } +        } + +        return 0; +err: +        return -1; + +} diff --git a/xlators/lib/src/libxlator.h b/xlators/lib/src/libxlator.h new file mode 100644 index 00000000000..be8a0093695 --- /dev/null +++ b/xlators/lib/src/libxlator.h @@ -0,0 +1,86 @@ +#ifndef _LIBXLATOR_H +#define _LIBXLATOR_H + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" +#include "logging.h" +#include "defaults.h" +#include "common-utils.h" +#include "compat.h" +#include "compat-errno.h" + + +#define MARKER_XATTR_PREFIX "trusted.glusterfs" +#define XTIME               "xtime" +#define VOLUME_MARK         "volume-mark" +#define GF_XATTR_MARKER_KEY MARKER_XATTR_PREFIX "." VOLUME_MARK +#define UUID_SIZE 36 +#define MARKER_UUID_TYPE    1 +#define MARKER_XTIME_TYPE   2 + + +typedef int32_t (*xlator_specf_unwind_t) (void *getxattr, call_frame_t *frame, +                                         int op_ret, int op_errno, dict_t *dict); + + +struct volume_mark { +        uint8_t major; +        uint8_t minor; +        uint8_t uuid[16]; +        uint8_t retval; +        uint32_t sec; +        uint32_t usec; +}__attribute__ ((__packed__)); + +struct marker_str { +        struct volume_mark    *volmark; +        data_t                *data; + +        uint32_t               host_timebuf[2]; +        uint32_t               net_timebuf[2]; +        int32_t                call_count; +        unsigned               has_xtime:1; +        int32_t                enoent_count; +        int32_t                enotconn_count; + +        xlator_specf_unwind_t  xl_specf_unwind; +        void                  *xl_local; +        char                  *vol_uuid; +}; + +static inline gf_boolean_t +marker_has_volinfo (struct marker_str *marker) +{ +       if (marker->volmark) +                return _gf_true; +       else +                return _gf_false; +} + +int32_t +cluster_markerxtime_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int op_ret, int op_errno, dict_t *dict); + +int32_t +cluster_markeruuid_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                        int op_ret, int op_errno, dict_t *dict); + +int32_t +cluster_getmarkerattr (call_frame_t *frame,xlator_t *this, loc_t *loc, +                       const char *name, void *xl_local, +                       xlator_specf_unwind_t xl_specf_getxattr_unwind, +                       xlator_t **sub_volumes, int count, int type, +                       char *vol_uuid); + +int +match_uuid_local (const char *name, char *uuid); + + + + +#endif /* !_LIBXLATOR_H */  | 
