diff options
| -rw-r--r-- | tests/basic/changelog/changelog-rename.t | 44 | ||||
| -rw-r--r-- | tests/utils/changelogparser.py | 234 | ||||
| -rw-r--r-- | tests/volume.rc | 7 | ||||
| -rw-r--r-- | xlators/cluster/dht/src/dht-rename.c | 11 | 
4 files changed, 296 insertions, 0 deletions
diff --git a/tests/basic/changelog/changelog-rename.t b/tests/basic/changelog/changelog-rename.t new file mode 100644 index 00000000000..9a0ef527b5b --- /dev/null +++ b/tests/basic/changelog/changelog-rename.t @@ -0,0 +1,44 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +cleanup; + +CHANGELOG_PATH_0="$B0/${V0}0/.glusterfs/changelogs" +ROLLOVER_TIME=30 + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}0 +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +touch $M0/file1 +mv $M0/file1 $M0/rn_file1 +mkdir $M0/dir1 +mv $M0/dir1 $M0/rn_dir1 + +EXPECT "2" check_changelog_op ${CHANGELOG_PATH_0} "RENAME" + +cleanup; + +#####Test on multiple subvolume##### +#==========================================# + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1} +TEST $CLI volume set $V0 changelog.changelog on +TEST $CLI volume set $V0 changelog.rollover-time $ROLLOVER_TIME +TEST $CLI volume start $V0 + +TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0; +touch $M0/gluster_file +mv $M0/gluster_file $M0/rn_gluster_file +mkdir $M0/dir1 +mv $M0/dir1 $M0/rn_dir1 + +EXPECT "2" check_changelog_op ${CHANGELOG_PATH_0} "RENAME" + +cleanup; diff --git a/tests/utils/changelogparser.py b/tests/utils/changelogparser.py new file mode 100644 index 00000000000..e173e52cbe6 --- /dev/null +++ b/tests/utils/changelogparser.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Why? + +Converts this + +GlusterFS Changelog | version: v1.1 | encoding : 2 +E0b99ef11-4b79-4cd0-9730-b5a0e8c4a8c0^@4^@16877^@0^@0^@00000000-0000-0000-0000- +000000000001/dir1^@Ec5250af6-720e-4bfe-b938-827614304f39^@23^@33188^@0^@0^@0b99 +ef11-4b79-4cd0-9730-b5a0e8c4a8c0/hello.txt^@Dc5250af6-720e-4bfe-b938-827614304f +39^@Dc5250af6-720e-4bfe-b938-827614304f39^@ + + +to human readable :) + +E 0b99ef11-4b79-4cd0-9730-b5a0e8c4a8c0 MKDIR 16877 0 000000000-0000-0000-0000 +  -000000000001/dir1 +E c5250af6-720e-4bfe-b938-827614304f39 CREATE 33188 0 0 0b99ef11-4b79-4cd0-9730 +  -b5a0e8c4a8c0/hello.txt +D c5250af6-720e-4bfe-b938-827614304f39 +D c5250af6-720e-4bfe-b938-827614304f39 + + +""" +import sys +import codecs + +ENTRY = 'E' +META = 'M' +DATA = 'D' +SEP = "\x00" + +GF_FOP = [ +    "NULL", "STAT", "READLINK", "MKNOD", "MKDIR", "UNLINK", +    "RMDIR", "SYMLINK", "RENAME", "LINK", "TRUNCATE", "OPEN", +    "READ", "WRITE", "STATFS", "FLUSH", "FSYNC", "SETXATTR", +    "GETXATTR", "REMOVEXATTR", "OPENDIR", "FSYNCDIR", "ACCESS", +    "CREATE", "FTRUNCATE", "FSTAT", "LK", "LOOKUP", "READDIR", +    "INODELK", "FINODELK", "ENTRYLK", "FENTRYLK", "XATTROP", +    "FXATTROP", "FSETXATTR", "FGETXATTR", "RCHECKSUM", "SETATTR", +    "FSETATTR", "READDIRP", "GETSPEC", "FORGET", "RELEASE", +    "RELEASEDIR", "FREMOVEXATTR", "FALLOCATE", "DISCARD", "ZEROFILL"] + + +class NumTokens_V11(object): +    E = 7 +    M = 3 +    D = 2 +    NULL = 3 +    MKNOD = 7 +    MKDIR = 7 +    UNLINK = 4 +    RMDIR = 4 +    SYMLINK = 4 +    RENAME = 5 +    LINK = 4 +    SETXATTR = 3 +    REMOVEXATTR = 3 +    CREATE = 7 +    SETATTR = 3 +    FTRUNCATE = 3 +    FXATTROP = 3 + + +class NumTokens_V12(NumTokens_V11): +    UNLINK = 5 +    RMDIR = 5 + + +class Version: +    V11 = "v1.1" +    V12 = "v1.2" + + +class Record(object): +    def __init__(self, **kwargs): +        self.ts = kwargs.get("ts", None) +        self.fop_type = kwargs.get("fop_type", None) +        self.gfid = kwargs.get("gfid", None) +        self.path = kwargs.get("path", None) +        self.fop = kwargs.get("fop", None) +        self.path1 = kwargs.get("path1", None) +        self.path2 = kwargs.get("path2", None) +        self.mode = kwargs.get("mode", None) +        self.uid = kwargs.get("uid", None) +        self.gid = kwargs.get("gid", None) + +    def create_mknod_mkdir(self, **kwargs): +        self.path = kwargs.get("path", None) +        self.fop = kwargs.get("fop", None) +        self.mode = kwargs.get("mode", None) +        self.uid = kwargs.get("uid", None) +        self.gid = kwargs.get("gid", None) + +    def metadata(self, **kwargs): +        self.fop = kwargs.get("fop", None) + +    def rename(self, **kwargs): +        self.fop = kwargs.get("fop", None) +        self.path1 = kwargs.get("path1", None) +        self.path2 = kwargs.get("path2", None) + +    def link_symlink_unlink_rmdir(self, **kwargs): +        self.path = kwargs.get("path", None) +        self.fop = kwargs.get("fop", None) + +    def __unicode__(self): +        if self.fop_type == "D": +            return u"{ts} {fop_type} {gfid}".format(**self.__dict__) +        elif self.fop_type == "M": +            return u"{ts} {fop_type} {gfid} {fop}".format(**self.__dict__) +        elif self.fop_type == "E": +            if self.fop in ["CREATE", "MKNOD", "MKDIR"]: +                return (u"{ts} {fop_type} {gfid} {fop} " +                        u"{path} {mode} {uid} {gid}".format(**self.__dict__)) +            elif self.fop == "RENAME": +                return (u"{ts} {fop_type} {gfid} {fop} " +                        u"{path1} {path2}".format(**self.__dict__)) +            elif self.fop in ["LINK", "SYMLINK", "UNLINK", "RMDIR"]: +                return (u"{ts} {fop_type} {gfid} {fop} " +                        u"{path}".format(**self.__dict__)) +            else: +                return repr(self.__dict__) +        else: +            return repr(self.__dict__) + +    def __str__(self): +        return unicode(self).encode('utf-8') + + +def get_num_tokens(data, tokens, version=Version.V11): +    if version == Version.V11: +        cls_numtokens = NumTokens_V11 +    elif version == Version.V12: +        cls_numtokens = NumTokens_V12 +    else: +        sys.stderr.write("Unknown Changelog Version\n") +        sys.exit(1) + +    if data[tokens[0]] in [ENTRY, META]: +        if len(tokens) >= 3: +            return getattr(cls_numtokens, GF_FOP[int(data[tokens[2]])]) +        else: +            return None +    else: +        return getattr(cls_numtokens, data[tokens[0]]) + + +def process_record(data, tokens, changelog_ts, callback): +    if data[tokens[0]] in [ENTRY, META]: +        try: +            tokens[2] = GF_FOP[int(data[tokens[2]])] +        except ValueError: +            tokens[2] = "NULL" + +    if not changelog_ts: +        ts1 = int(changelog_ts) +    else: +        ts1="" +    record = Record(ts=ts1, fop_type=data[tokens[0]], +                    gfid=data[tokens[1]]) +    if data[tokens[0]] == META: +        record.metadata(fop=tokens[2]) +    elif data[tokens[0]] == ENTRY: +        if tokens[2] in ["CREATE", "MKNOD", "MKDIR"]: +            record.create_mknod_mkdir(fop=tokens[2], +                                      path=data[tokens[6]], +                                      mode=int(data[tokens[3]]), +                                      uid=int(data[tokens[4]]), +                                      gid=int(data[tokens[5]])) +        elif tokens[2] == "RENAME": +            record.rename(fop=tokens[2], +                          path1=data[tokens[3]], +                          path2=data[tokens[4]]) +        if tokens[2] in ["LINK", "SYMLINK", "UNLINK", "RMDIR"]: +            record.link_symlink_unlink_rmdir(fop=tokens[2], +                                             path=data[tokens[3]]) +    callback(record) + + +def default_callback(record): +    sys.stdout.write(u"{0}\n".format(record)) + + +def parse(filename, callback=default_callback): +    data = None +    tokens = [] +    changelog_ts = filename.rsplit(".")[-1] +    with codecs.open(filename, mode="rb", encoding="utf-8") as f: +        # GlusterFS Changelog | version: v1.1 | encoding : 2 +        header = f.readline() +        version = header.split()[4] + +        data = f.readline() + +        slice_start = 0 +        in_record = False + +        prev_char = "" +        next_char = "" +        for i, c in enumerate(data): +            next_char = "" +            if len(data) >= (i + 2): +                next_char = data[i+1] + +            if not in_record and c in [ENTRY, META, DATA]: +                tokens.append(slice(slice_start, i+1)) +                slice_start = i+1 +                in_record = True +                continue + +            if c == SEP and ((prev_char != SEP and next_char == SEP) or +                             (prev_char == SEP and next_char != SEP) or +                             (prev_char != SEP and next_char != SEP)): +                tokens.append(slice(slice_start, i)) +                slice_start = i+1 + +                num_tokens = get_num_tokens(data, tokens, version) + +                if num_tokens == len(tokens): +                    process_record(data, tokens, changelog_ts, callback) +                    in_record = False +                    tokens = [] + +            prev_char = c + +        # process last record +        if slice_start < (len(data) - 1): +            tokens.append(slice(slice_start, len(data))) +            process_record(data, tokens, changelog_ts, callback) +            tokens = [] + +parse(sys.argv[1]) diff --git a/tests/volume.rc b/tests/volume.rc index 492b08a4d9d..ba0fac7bfc9 100644 --- a/tests/volume.rc +++ b/tests/volume.rc @@ -869,3 +869,10 @@ function get_mount_lru_size_value {          rm -f $statedump          echo $val  } + +function check_changelog_op { +        local clog_path=$1 +        local op=$2 + +        $PYTHON $(dirname $0)/../../utils/changelogparser.py ${clog_path}/CHANGELOG | grep $op | wc -l +} diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c index d311ac633e3..1d0c2bbc7ed 100644 --- a/xlators/cluster/dht/src/dht-rename.c +++ b/xlators/cluster/dht/src/dht-rename.c @@ -1948,6 +1948,7 @@ dht_rename (call_frame_t *frame, xlator_t *this,          dht_conf_t  *conf                   = NULL;          char         gfid[GF_UUID_BUF_SIZE] = {0};          char         newgfid[GF_UUID_BUF_SIZE] = {0}; +        gf_boolean_t free_xdata             = _gf_false;          VALIDATE_OR_GOTO (frame, err);          VALIDATE_OR_GOTO (this, err); @@ -1957,7 +1958,17 @@ dht_rename (call_frame_t *frame, xlator_t *this,          conf = this->private;          if (conf->subvolume_cnt == 1) { +                if (!IA_ISDIR (oldloc->inode->ia_type)) { +                        if (!xdata) { +                                free_xdata = _gf_true; +                        } +                        DHT_CHANGELOG_TRACK_AS_RENAME(xdata, oldloc, newloc); +                }                  default_rename (frame, this, oldloc, newloc, xdata); +                if (free_xdata && xdata) { +                        dict_unref(xdata); +                        xdata = NULL; +                }                  return 0;          }  | 
