* added file locking around cache
[invirt/packages/invirt-base.git] / files / usr / share / python-support / sipb-xen-base / invirt / config.py
index fad48fe..02409a4 100644 (file)
@@ -1,10 +1,9 @@
 import json, yaml
 from invirt.common import *
 import json, yaml
 from invirt.common import *
-from os import error, makedirs
-from os.path import dirname, getmtime
+from os.path import getmtime
 
 default_src_path   = '/etc/invirt/master.yaml'
 
 default_src_path   = '/etc/invirt/master.yaml'
-default_cache_path = '/var/lib/invirt/invirt.json'
+default_cache_path = '/var/lib/invirt/cache.json'
 
 try:    default_loader = yaml.CSafeLoader
 except: default_loader = yaml.SafeLoader
 
 try:    default_loader = yaml.CSafeLoader
 except: default_loader = yaml.SafeLoader
@@ -28,14 +27,19 @@ def load(src_path = default_src_path,
 
     if not do_refresh:
         # try reading from the cache first
 
     if not do_refresh:
         # try reading from the cache first
-        try: cfg = wrap(file(cache_path), lambda f: json.read(f.read()))
+        try: cfg = with_closing(file(cache_path))(lambda f: json.read(f.read()))
         except: do_refresh = True
 
     if do_refresh:
         except: do_refresh = True
 
     if do_refresh:
-        # reload the source and regenerate the cache
-        cfg = wrap(file(src_path), lambda f: yaml.load(f, default_loader))
-        try: wrap(file(cache_path, 'w'), lambda f: f.write(json.write(cfg)))
-        except: pass # silent failure
+        # Atomically reload the source and regenerate the cache.  The read and
+        # write must be a single transaction, or a stale version may be
+        # written.
+        @with_lock_file('/var/lib/invirt/cache.lock')
+        def cfg():
+            cfg = with_closing(file(src_path))(lambda f: yaml.load(f, default_loader))
+            try: with_closing(file(cache_path, 'w'))(lambda f: f.write(json.write(cfg)))
+            except: pass # silent failure
+            return cfg
     return cfg
 
 dicts = load()
     return cfg
 
 dicts = load()