ia64/xen-unstable

view tools/python/xen/xend/xenstore/xstransact.py @ 7081:7c5d9879967d

Added behaviour to list() to list the transaction's path if no arguments are
given. Added list_recursive().

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Tue Sep 27 22:02:57 2005 +0100 (2005-09-27)
parents 10d6bda59ea4
children a65cdee92c0f
line source
1 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
2 # Copyright (C) 2005 XenSource Ltd
4 # This file is subject to the terms and conditions of the GNU General
5 # Public License. See the file "COPYING" in the main directory of
6 # this archive for more details.
8 import errno
9 import threading
10 from xen.lowlevel import xs
11 from xen.xend.xenstore.xsutil import xshandle
14 class xstransact:
16 def __init__(self, path):
17 self.in_transaction = False
18 self.path = path.rstrip("/")
19 xshandle().transaction_start()
20 self.in_transaction = True
22 def __del__(self):
23 if self.in_transaction:
24 xshandle().transaction_end(True)
26 def commit(self):
27 if not self.in_transaction:
28 raise RuntimeError
29 self.in_transaction = False
30 return xshandle().transaction_end(False)
32 def abort(self):
33 self.in_transaction = False
34 return xshandle().transaction_end(True)
36 def _read(self, key):
37 path = "%s/%s" % (self.path, key)
38 try:
39 return xshandle().read(path)
40 except RuntimeError, ex:
41 raise RuntimeError(ex.args[0],
42 '%s, while reading %s' % (ex.args[1], path))
44 def read(self, *args):
45 if len(args) == 0:
46 raise TypeError
47 if len(args) == 1:
48 return self._read(args[0])
49 ret = []
50 for key in args:
51 ret.append(self._read(key))
52 return ret
54 def _write(self, key, data):
55 path = "%s/%s" % (self.path, key)
56 try:
57 xshandle().write(path, data)
58 except RuntimeError, ex:
59 raise RuntimeError(ex.args[0],
60 ('%s, while writing %s : %s' %
61 (ex.args[1], path, str(data))))
63 def write(self, *args, **opts):
64 if len(args) == 0:
65 raise TypeError
66 if isinstance(args[0], dict):
67 for d in args:
68 if not isinstance(d, dict):
69 raise TypeError
70 for key in d.keys():
71 try:
72 self._write(key, d[key])
73 except TypeError, msg:
74 raise TypeError('Writing %s: %s: %s' %
75 (key, str(d[key]), msg))
76 elif isinstance(args[0], list):
77 for l in args:
78 if not len(l) == 2:
79 raise TypeError
80 self._write(l[0], l[1])
81 elif len(args) % 2 == 0:
82 for i in range(len(args) / 2):
83 self._write(args[i * 2], args[i * 2 + 1])
84 else:
85 raise TypeError
87 def _remove(self, key):
88 path = "%s/%s" % (self.path, key)
89 return xshandle().rm(path)
91 def remove(self, *args):
92 """If no arguments are given, remove this transaction's path.
93 Otherwise, treat each argument as a subpath to this transaction's
94 path, and remove each of those instead.
95 """
96 if len(args) == 0:
97 xshandle().rm(self.path)
98 else:
99 for key in args:
100 self._remove(key)
102 def _list(self, key):
103 path = "%s/%s" % (self.path, key)
104 l = xshandle().ls(path)
105 if l:
106 return map(lambda x: key + "/" + x, l)
107 return []
109 def list(self, *args):
110 """If no arguments are given, list this transaction's path, returning
111 the entries therein, or None if no entries are found. Otherwise,
112 treat each argument as a subpath to this transaction's path, and
113 return the cumulative listing of each of those instead.
114 """
115 if len(args) == 0:
116 return xshandle().ls(self.path)
117 else:
118 ret = []
119 for key in args:
120 ret.extend(self._list(key))
121 return ret
124 def list_recursive_(self, subdir, keys):
125 ret = []
126 for key in keys:
127 new_subdir = subdir + "/" + key
128 l = xshandle().ls(new_subdir)
129 if l:
130 ret.append([key, self.list_recursive_(new_subdir, l)])
131 else:
132 ret.append([key, xshandle().read(new_subdir)])
133 return ret
136 def list_recursive(self, *args):
137 if len(args) == 0:
138 args = self.list()
140 return self.list_recursive_(self.path, args)
143 def gather(self, *args):
144 if len(args) and type(args[0]) != tuple:
145 args = args,
146 ret = []
147 for tup in args:
148 if len(tup) == 2:
149 (key, fn) = tup
150 defval = None
151 else:
152 (key, fn, defval) = tup
154 val = self._read(key)
155 # If fn is str, then this will successfully convert None to
156 # 'None'. If it is int, then it will throw TypeError on None, or
157 # on any other non-integer value. We have to, therefore, both
158 # check explicitly for None, and catch TypeError. Either failure
159 # will result in defval being used instead.
160 if val is None:
161 val = defval
162 else:
163 try:
164 val = fn(val)
165 except TypeError:
166 val = defval
167 ret.append(val)
168 if len(ret) == 1:
169 return ret[0]
170 return ret
172 def store(self, *args):
173 if len(args) and type(args[0]) != tuple:
174 args = args,
175 for tup in args:
176 if len(tup) == 2:
177 (key, val) = tup
178 try:
179 fmt = { str : "%s",
180 int : "%i",
181 float : "%f",
182 type(None) : None }[type(val)]
183 except KeyError:
184 raise TypeError
185 else:
186 (key, val, fmt) = tup
187 if val is None:
188 self._remove(key)
189 else:
190 self._write(key, fmt % val)
193 def Read(cls, path, *args):
194 while True:
195 t = cls(path)
196 try:
197 v = t.read(*args)
198 t.abort()
199 return v
200 except:
201 t.abort()
202 raise
204 Read = classmethod(Read)
206 def Write(cls, path, *args, **opts):
207 while True:
208 t = cls(path)
209 try:
210 t.write(*args, **opts)
211 if t.commit():
212 return
213 except:
214 t.abort()
215 raise
217 Write = classmethod(Write)
219 def Remove(cls, path, *args):
220 """If only one argument is given (path), remove it. Otherwise, treat
221 each further argument as a subpath to the given path, and remove each
222 of those instead. This operation is performed inside a transaction.
223 """
224 while True:
225 t = cls(path)
226 try:
227 t.remove(*args)
228 if t.commit():
229 return
230 except:
231 t.abort()
232 raise
234 Remove = classmethod(Remove)
236 def List(cls, path, *args):
237 while True:
238 t = cls(path)
239 try:
240 v = t.list(*args)
241 if t.commit():
242 return v
243 except:
244 t.abort()
245 raise
247 List = classmethod(List)
249 def Gather(cls, path, *args):
250 while True:
251 t = cls(path)
252 try:
253 v = t.gather(*args)
254 if t.commit():
255 return v
256 except:
257 t.abort()
258 raise
260 Gather = classmethod(Gather)
262 def Store(cls, path, *args):
263 while True:
264 t = cls(path)
265 try:
266 v = t.store(*args)
267 if t.commit():
268 return v
269 except:
270 t.abort()
271 raise
273 Store = classmethod(Store)