summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoren Hansen <soren@linux2go.dk>2011-02-28 12:37:02 +0100
committerSoren Hansen <soren@linux2go.dk>2011-02-28 12:37:02 +0100
commit8b3e9ad11c2f5c425701f1eb4abb7b3f577ae1cc (patch)
treee11aa4a0eb4188b998b91c65970682a5c61ac0b6
parentedf5da85648659b1a7ad105248d69ef9f8c977e4 (diff)
downloadnova-8b3e9ad11c2f5c425701f1eb4abb7b3f577ae1cc.tar.gz
nova-8b3e9ad11c2f5c425701f1eb4abb7b3f577ae1cc.tar.xz
nova-8b3e9ad11c2f5c425701f1eb4abb7b3f577ae1cc.zip
Add utils.synchronized decorator to allow for synchronising method entrance across multiple workers on the same host.
-rw-r--r--nova/tests/test_misc.py37
-rw-r--r--nova/utils.py11
2 files changed, 47 insertions, 1 deletions
diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py
index e6da6112a..154b6fae6 100644
--- a/nova/tests/test_misc.py
+++ b/nova/tests/test_misc.py
@@ -14,10 +14,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from datetime import datetime
+import errno
import os
+import select
+import time
from nova import test
-from nova.utils import parse_mailmap, str_dict_replace
+from nova.utils import parse_mailmap, str_dict_replace, synchronized
class ProjectTestCase(test.TestCase):
@@ -55,3 +59,34 @@ class ProjectTestCase(test.TestCase):
'%r not listed in Authors' % missing)
finally:
tree.unlock()
+
+
+class LockTestCase(test.TestCase):
+ def test_synchronized(self):
+ rpipe, wpipe = os.pipe()
+ pid = os.fork()
+ if pid > 0:
+ os.close(wpipe)
+
+ @synchronized('testlock')
+ def f():
+ rfds, _, __ = select.select([rpipe], [], [], 1)
+ self.assertEquals(len(rfds), 0, "The other process, which was"
+ " supposed to be locked, "
+ "wrote on its end of the "
+ "pipe")
+ os.close(rpipe)
+
+ f()
+ else:
+ os.close(rpipe)
+
+ @synchronized('testlock')
+ def g():
+ try:
+ os.write(wpipe, "foo")
+ except OSError, e:
+ self.assertEquals(e.errno, errno.EPIPE)
+ return
+ g()
+ os._exit(0)
diff --git a/nova/utils.py b/nova/utils.py
index 0cf91e0cc..cb1ea5a7d 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -25,6 +25,7 @@ import base64
import datetime
import inspect
import json
+import lockfile
import os
import random
import socket
@@ -491,6 +492,16 @@ def loads(s):
return json.loads(s)
+def synchronized(name):
+ def wrap(f):
+ def inner(*args, **kwargs):
+ lock = lockfile.FileLock('nova-%s.lock' % name)
+ with lock:
+ return f(*args, **kwargs)
+ return inner
+ return wrap
+
+
def ensure_b64_encoding(val):
"""Safety method to ensure that values expected to be base64-encoded
actually are. If they are, the value is returned unchanged. Otherwise,