xen-vt-testing

view tools/python/xen/xend/xenstore/xstransact.py @ 6710:54af57682431

Only retry transactions which fail from timeout.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Fri Sep 09 17:03:34 2005 +0000 (2005-09-09)
parents d0b3c7061368
children 1a27091a1e7a
line source
1 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
3 # This file is subject to the terms and conditions of the GNU General
4 # Public License. See the file "COPYING" in the main directory of
5 # this archive for more details.
7 import errno
8 import threading
9 from xen.lowlevel import xs
11 handles = {}
13 # XXX need to g/c handles from dead threads
14 def xshandle():
15 if not handles.has_key(threading.currentThread()):
16 handles[threading.currentThread()] = xs.open()
17 return handles[threading.currentThread()]
19 class xstransact:
21 def __init__(self, path):
22 self.in_transaction = False
23 self.path = path.rstrip("/")
24 while True:
25 try:
26 xshandle().transaction_start(path)
27 self.in_transaction = True
28 return
29 except RuntimeError, ex:
30 if ex.args[0] == errno.ENOENT and path != "/":
31 path = "/".join(path.split("/")[0:-1]) or "/"
32 else:
33 raise
35 def __del__(self):
36 if self.in_transaction:
37 xshandle().transaction_end(True)
39 def commit(self):
40 if not self.in_transaction:
41 raise RuntimeError
42 self.in_transaction = False
43 return xshandle().transaction_end(False)
45 def abort(self):
46 if not self.in_transaction:
47 raise RuntimeError
48 self.in_transaction = False
49 return xshandle().transaction_end(True)
51 def _read(self, key):
52 path = "%s/%s" % (self.path, key)
53 return xshandle().read(path)
55 def read(self, *args):
56 if len(args) == 0:
57 raise TypeError
58 if len(args) == 1:
59 return self._read(args[0])
60 ret = []
61 for key in args:
62 ret.append(self._read(key))
63 return ret
65 def _write(self, key, data, create=True, excl=False):
66 path = "%s/%s" % (self.path, key)
67 xshandle().write(path, data, create=create, excl=excl)
69 def write(self, *args, **opts):
70 create = opts.get('create') or True
71 excl = opts.get('excl') or False
72 if len(args) == 0:
73 raise TypeError
74 if isinstance(args[0], dict):
75 for d in args:
76 if not isinstance(d, dict):
77 raise TypeError
78 for key in d.keys():
79 self._write(key, d[key], create, excl)
80 elif isinstance(args[0], list):
81 for l in args:
82 if not len(l) == 2:
83 raise TypeError
84 self._write(l[0], l[1], create, excl)
85 elif len(args) % 2 == 0:
86 for i in range(len(args) / 2):
87 self._write(args[i * 2], args[i * 2 + 1], create, excl)
88 else:
89 raise TypeError
91 def Read(cls, path, *args):
92 t = cls(path)
93 v = t.read(*args)
94 t.commit()
95 return v
97 Read = classmethod(Read)
99 def Write(cls, path, *args, **opts):
100 t = cls(path)
101 t.write(*args, **opts)
102 t.commit()
104 Write = classmethod(Write)
106 def SafeRead(cls, path, *args):
107 while True:
108 try:
109 return cls.Read(path, *args)
110 except RuntimeError, ex:
111 if ex.args[0] == errno.ETIMEDOUT:
112 pass
113 raise
115 SafeRead = classmethod(SafeRead)
117 def SafeWrite(cls, path, *args, **opts):
118 while True:
119 try:
120 cls.Write(path, *args, **opts)
121 return
122 except RuntimeError, ex:
123 if ex.args[0] == errno.ETIMEDOUT:
124 pass
125 raise
127 SafeWrite = classmethod(SafeWrite)