From de22a7760db69b82de8959d238fe444af8b387d0 Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Wed, 18 Jul 2012 03:59:00 +0200 Subject: geo-rep / gsyncd: add support for sending xtimes through rsync Note that in said mode metadata synchronization is best effort: rsync syncs metadata at last so if rsync is interrupted in between xattr sync and metadata sync stages, then file will be considered in sync Change-Id: I1c75eab33b0a1000abf3ad36b2d484a89eeda1bd BUG: 841062 Signed-off-by: Csaba Henk Reviewed-on: http://review.gluster.com/3683 Tested-by: Gluster Build System Reviewed-by: Venky Shankar --- xlators/features/marker/utils/syncdaemon/gsyncd.py | 3 ++- xlators/features/marker/utils/syncdaemon/master.py | 28 ++++++++++++++++------ .../features/marker/utils/syncdaemon/resource.py | 18 +++++++++----- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/xlators/features/marker/utils/syncdaemon/gsyncd.py b/xlators/features/marker/utils/syncdaemon/gsyncd.py index 17b10e5a..9e946946 100644 --- a/xlators/features/marker/utils/syncdaemon/gsyncd.py +++ b/xlators/features/marker/utils/syncdaemon/gsyncd.py @@ -159,6 +159,7 @@ def main_i(): op.add_option('-l', '--log-file', metavar='LOGF', type=str, action='callback', callback=store_abs) op.add_option('--state-file', metavar='STATF', type=str, action='callback', callback=store_abs) op.add_option('--ignore-deletes', default=False, action='store_true') + op.add_option('--use-rsync-xattrs', default=False, action='store_true') op.add_option('-L', '--log-level', metavar='LVL') op.add_option('-r', '--remote-gsyncd', metavar='CMD', default=os.path.abspath(sys.argv[0])) op.add_option('--volume-id', metavar='UUID') @@ -213,7 +214,7 @@ def main_i(): op.add_option('--canonicalize-escape-url', dest='url_print', action='callback', callback=store_local_curry('canon_esc')) tunables = [ norm(o.get_opt_string()[2:]) for o in op.option_list if o.callback in (store_abs, 'store_true', None) and o.get_opt_string() not in ('--version', '--help') ] - remote_tunables = [ 'listen', 'go_daemon', 'timeout', 'session_owner', 'config_file' ] + remote_tunables = [ 'listen', 'go_daemon', 'timeout', 'session_owner', 'config_file', 'use_rsync_xattrs' ] rq_remote_tunables = { 'listen': True } # precedence for sources of values: 1) commandline, 2) cfg file, 3) defaults diff --git a/xlators/features/marker/utils/syncdaemon/master.py b/xlators/features/marker/utils/syncdaemon/master.py index 945ebb75..a6aeb53d 100644 --- a/xlators/features/marker/utils/syncdaemon/master.py +++ b/xlators/features/marker/utils/syncdaemon/master.py @@ -54,12 +54,13 @@ def gmaster_builder(): """produce the GMaster class variant corresponding to sync mode""" this = sys.modules[__name__] - mixin = gconf.special_sync_mode - if not mixin: - mixin = 'normal' - logging.info('setting up master for %s sync mode' % mixin) - mixin = getattr(this, mixin.capitalize() + 'Mixin') - class _GMaster(GMasterBase, mixin): + modemixin = gconf.special_sync_mode + if not modemixin: + modemixin = 'normal' + logging.info('setting up master for %s sync mode' % modemixin) + modemixin = getattr(this, modemixin.capitalize() + 'Mixin') + sendmarkmixin = boolify(gconf.use_rsync_xattrs) and SendmarkNormalMixin or SendmarkRsyncMixin + class _GMaster(GMasterBase, modemixin, sendmarkmixin): pass return _GMaster @@ -295,6 +296,19 @@ class BlindMixin(object): self.slave.server.set_xtime_vec(path, xtd) +# Further mixins for certain tunable behaviors + +class SendmarkNormalMixin(object): + + def sendmark_regular(self, *a, **kw): + return self.sendmark(self, *a, **kw) + +class SendmarkRsyncMixin(object): + + def sendmark_regular(self, *a, **kw): + pass + + class GMasterBase(object): """abstract class impementling master role""" @@ -753,7 +767,7 @@ class GMasterBase(object): def regjob(e, xte, pb): if pb.wait(): logging.debug("synced " + e) - self.sendmark(e, xte) + self.sendmark_regular(e, xte) return True else: logging.warn("failed to sync " + e) diff --git a/xlators/features/marker/utils/syncdaemon/resource.py b/xlators/features/marker/utils/syncdaemon/resource.py index 9ca226f9..47e4748d 100644 --- a/xlators/features/marker/utils/syncdaemon/resource.py +++ b/xlators/features/marker/utils/syncdaemon/resource.py @@ -19,7 +19,7 @@ import repce from repce import RepceServer, RepceClient from master import gmaster_builder import syncdutils -from syncdutils import GsyncdError, select, privileged +from syncdutils import GsyncdError, select, privileged, boolify UrlRX = re.compile('\A(\w+)://([^ *?[]*)\Z') HostRX = re.compile('[a-z\d](?:[a-z\d.-]*[a-z\d])?', re.I) @@ -472,6 +472,10 @@ class SlaveLocal(object): stop servicing if a timeout is configured and got no keep-alime in that inteval """ + + if boolify(gconf.use_rsync_xattrs) and not privileged(): + raise GsyncdError("using rsync for extended attributes is not supported") + repce = RepceServer(self.server, sys.stdin, sys.stdout, int(gconf.sync_jobs)) t = syncdutils.Thread(target=lambda: (repce.service_loop(), syncdutils.finalize())) @@ -498,12 +502,13 @@ class SlaveRemote(object): communicate throuh its stdio. """ slave = opts.get('slave', self.url) + extra_opts = [] so = getattr(gconf, 'session_owner', None) if so: - so_args = ['--session-owner', so] - else: - so_args = [] - po = Popen(rargs + gconf.remote_gsyncd.split() + so_args + \ + extra_opts += ['--session-owner', so] + if boolify(gconf.use_rsync_xattrs): + extra_opts.append('--use-rsync-xattrs') + po = Popen(rargs + gconf.remote_gsyncd.split() + extra_opts + \ ['-N', '--listen', '--timeout', str(gconf.timeout), slave], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) gconf.transport = po @@ -532,7 +537,8 @@ class SlaveRemote(object): raise GsyncdError("no files to sync") logging.debug("files: " + ", ".join(files)) argv = gconf.rsync_command.split() + ['-aR', '--super', '--numeric-ids', '--no-implied-dirs'] + \ - gconf.rsync_options.split() + files + list(args) + gconf.rsync_options.split() + (boolify(gconf.use_rsync_xattrs) and ['--xattrs'] or []) + \ + files + list(args) po = Popen(argv, stderr=subprocess.PIPE) po.wait() po.terminate_geterr(fail_on_err = False) -- cgit