diff options
author | Csaba Henk <csaba@gluster.com> | 2011-04-02 19:40:48 +0000 |
---|---|---|
committer | Vijay Bellur <vijay@dev.gluster.com> | 2011-04-04 08:02:22 -0700 |
commit | e77c35248e8ce796bc5b108c10013089a0c65bde (patch) | |
tree | 10e7eda370a3bb9c35ed3f965e84c2063ca47195 | |
parent | cfb9c834f96dc57c47dac8d27da4266d0dab1f3f (diff) |
syncdaemon: provide transactional semantics to config file writing
So updating the config file from multiple contexts won't mess it up.
This prepares the next commit where we'll set options internaly (which lacks
the serial nature of user actions).
Signed-off-by: Csaba Henk <csaba@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 2537 (gsync autorestart)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2537
-rw-r--r-- | xlators/features/marker/utils/syncdaemon/configinterface.py | 31 | ||||
-rw-r--r-- | xlators/features/marker/utils/syncdaemon/syncdutils.py | 31 |
2 files changed, 49 insertions, 13 deletions
diff --git a/xlators/features/marker/utils/syncdaemon/configinterface.py b/xlators/features/marker/utils/syncdaemon/configinterface.py index cda7da7ebf3..a1079d80394 100644 --- a/xlators/features/marker/utils/syncdaemon/configinterface.py +++ b/xlators/features/marker/utils/syncdaemon/configinterface.py @@ -109,19 +109,19 @@ class GConffile(object): continue print("%s: %s" % (k, v)) - def write(self): - if not self.config.has_section(SECT_META): - self.config.add_section(SECT_META) - self.config.set(SECT_META, 'version', config_version) - f = None - try: - f = open(self.path, 'wb') + def write(self, trfn, *a, **kw): + def mergeconf(f): + self.config = ConfigParser.RawConfigParser() + self.config.readfp(f) + def updateconf(f): + if not self.config.has_section(SECT_META): + self.config.add_section(SECT_META) + self.config.set(SECT_META, 'version', config_version) + trfn(*a, **kw) self.config.write(f) - finally: - if f: - f.close() + syncdutils.update_file(self.path, updateconf, mergeconf) - def set(self, opt, val, rx=False): + def _set(self, opt, val, rx=False): sect = self.section(rx) if not self.config.has_section(sect): self.config.add_section(sect) @@ -130,11 +130,16 @@ class GConffile(object): self.config.add_section(SECT_ORD) self.config.set(SECT_ORD, sect, len(self.config._sections[SECT_ORD])) self.config.set(sect, opt, val) - self.write() - def delete(self, opt, rx=False): + def set(self, *a, **kw): + self.write(self._set, *a, **kw) + + def _delete(self, opt, rx=False): sect = self.section(rx) if not self.config.has_section(sect): return if self.config.remove_option(sect, opt): self.write() + + def delete(self, *a, **kw): + self.write(self._delete, *a, **kw) diff --git a/xlators/features/marker/utils/syncdaemon/syncdutils.py b/xlators/features/marker/utils/syncdaemon/syncdutils.py index 52dad8c5ff3..723ab8fb5fc 100644 --- a/xlators/features/marker/utils/syncdaemon/syncdutils.py +++ b/xlators/features/marker/utils/syncdaemon/syncdutils.py @@ -1,3 +1,5 @@ +import os +import fcntl try: # py 3 from urllib import parse as urllib @@ -9,3 +11,32 @@ def escape(s): def unescape(s): return urllib.unquote_plus(s) + +def update_file(path, updater, merger = lambda f: True): + """update a file in a transaction-like manner""" + + fr = fw = None + try: + fd = os.open(path, os.O_CREAT|os.O_RDWR) + try: + fr = os.fdopen(fd, 'r+b') + except: + os.close(fd) + raise + fcntl.lockf(fr, fcntl.LOCK_EX) + merger(fr) + + tmpp = path + '.tmp.' + str(os.getpid()) + fd = os.open(tmpp, os.O_CREAT|os.O_EXCL|os.O_WRONLY) + try: + fw = os.fdopen(fd, 'wb', 0) + except: + os.close(fd) + raise + updater(fw) + os.fsync(fd) + os.rename(tmpp, path) + finally: + for fx in (fr, fw): + if fx: + fx.close() |