Ignore:
Timestamp:
Jul 29, 2008, 10:35:08 PM (16 years ago)
Author:
y_z
Message:
  • added file locking around cache
  • cleanup
Location:
trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/common.py

    r778 r781  
    11import unittest
     2from fcntl import flock, LOCK_EX, LOCK_UN
     3from os import remove
    24
    35class struct(object):
    46    'A simple namespace object.'
    5     def __init__(self, d = {}):
     7    def __init__(self, d = {}, **kwargs):
    68        'd is the dictionary to update my __dict__ with.'
    79        self.__dict__.update(d)
     10        self.__dict__.update(kwargs)
    811
    912def dicts2struct(x):
     
    1922        return x
    2023
    21 def wrap(rsrc, func):
    22     "Utility to that emulates with Python 2.5's `with closing(rsrc)`."
    23     try: return func(rsrc)
    24     finally: rsrc.close()
     24#
     25# Hacks to work around lack of Python 2.5's `with` statement.
     26#
     27
     28def with_closing(rsrc):
     29    "Utility to emulate Python 2.5's `with closing(rsrc)` context manager."
     30    def wrapper(func):
     31        try: return func(rsrc)
     32        finally: rsrc.close()
     33    return wrapper
     34
     35def with_lock_file(path):
     36    """
     37    Context manager for lock files.  Example:
     38
     39    @with_lock_file('/tmp/mylock')
     40    def input():
     41        print 'locked'
     42        return raw_input()
     43    # decorator is executed immediately
     44    print input # prints the input text
     45    """
     46    def wrapper(func):
     47        @with_closing(file(path, 'w'))
     48        def g(f):
     49            flock(f, LOCK_EX)
     50            try: return func()
     51            finally: flock(f, LOCK_UN)
     52        remove(path)
     53        return g
     54    return wrapper
     55
     56#
     57# Tests.
     58#
    2559
    2660class common_tests(unittest.TestCase):
  • trunk/packages/sipb-xen-base/files/usr/share/python-support/sipb-xen-base/invirt/config.py

    r778 r781  
    11import json, yaml
    22from invirt.common import *
    3 from os import error, makedirs
    4 from os.path import dirname, getmtime
     3from os.path import getmtime
    54
    65default_src_path   = '/etc/invirt/master.yaml'
    7 default_cache_path = '/var/lib/invirt/invirt.json'
     6default_cache_path = '/var/lib/invirt/cache.json'
    87
    98try:    default_loader = yaml.CSafeLoader
     
    2928    if not do_refresh:
    3029        # try reading from the cache first
    31         try: cfg = wrap(file(cache_path), lambda f: json.read(f.read()))
     30        try: cfg = with_closing(file(cache_path))(lambda f: json.read(f.read()))
    3231        except: do_refresh = True
    3332
    3433    if do_refresh:
    35         # reload the source and regenerate the cache
    36         cfg = wrap(file(src_path), lambda f: yaml.load(f, default_loader))
    37         try: wrap(file(cache_path, 'w'), lambda f: f.write(json.write(cfg)))
    38         except: pass # silent failure
     34        # Atomically reload the source and regenerate the cache.  The read and
     35        # write must be a single transaction, or a stale version may be
     36        # written.
     37        @with_lock_file('/var/lib/invirt/cache.lock')
     38        def cfg():
     39            cfg = with_closing(file(src_path))(lambda f: yaml.load(f, default_loader))
     40            try: with_closing(file(cache_path, 'w'))(lambda f: f.write(json.write(cfg)))
     41            except: pass # silent failure
     42            return cfg
    3943    return cfg
    4044
Note: See TracChangeset for help on using the changeset viewer.