debuggers.hg

view tools/python/xen/xend/xenstore/xstransact.py @ 12653:1b501311c778

Move the assert under the protection of the in_transaction flag.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Nov 29 12:15:45 2006 +0000 (2006-11-29)
parents 956f7c5b1c1f
children 9fe92a88912b
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 from xen.xend.xenstore.xsutil import xshandle
11 class xstransact:
13 def __init__(self, path = ""):
15 self.in_transaction = False # Set this temporarily -- if this
16 # constructor fails, then we need to
17 # protect __del__.
19 assert path is not None
20 self.path = path.rstrip("/")
21 self.transaction = xshandle().transaction_start()
22 self.in_transaction = True
24 def __del__(self):
25 if self.in_transaction:
26 xshandle().transaction_end(self.transaction, True)
28 def commit(self):
29 if not self.in_transaction:
30 raise RuntimeError
31 self.in_transaction = False
32 rc = xshandle().transaction_end(self.transaction, False)
33 self.transaction = "0"
34 return rc
36 def abort(self):
37 if not self.in_transaction:
38 return True
39 self.in_transaction = False
40 rc = xshandle().transaction_end(self.transaction, True)
41 self.transaction = "0"
42 return rc
44 def _read(self, key):
45 path = self.prependPath(key)
46 try:
47 return xshandle().read(self.transaction, path)
48 except RuntimeError, ex:
49 raise RuntimeError(ex.args[0],
50 '%s, while reading %s' % (ex.args[1], path))
52 def read(self, *args):
53 """If no arguments are given, return the value at this transaction's
54 path. If one argument is given, treat that argument as a subpath to
55 this transaction's path, and return the value at that path.
56 Otherwise, treat each argument as a subpath to this transaction's
57 path, and return a list composed of the values at each of those
58 instead.
59 """
60 if len(args) == 0:
61 return xshandle().read(self.transaction, self.path)
62 if len(args) == 1:
63 return self._read(args[0])
64 ret = []
65 for key in args:
66 ret.append(self._read(key))
67 return ret
69 def _write(self, key, data):
70 path = self.prependPath(key)
71 try:
72 xshandle().write(self.transaction, path, data)
73 except RuntimeError, ex:
74 raise RuntimeError(ex.args[0],
75 ('%s, while writing %s : %s' %
76 (ex.args[1], path, str(data))))
78 def write(self, *args):
79 if len(args) == 0:
80 raise TypeError
81 if isinstance(args[0], dict):
82 for d in args:
83 if not isinstance(d, dict):
84 raise TypeError
85 for key in d.keys():
86 try:
87 self._write(key, d[key])
88 except TypeError, msg:
89 raise TypeError('Writing %s: %s: %s' %
90 (key, str(d[key]), msg))
91 elif isinstance(args[0], list):
92 for l in args:
93 if not len(l) == 2:
94 raise TypeError
95 self._write(l[0], l[1])
96 elif len(args) % 2 == 0:
97 for i in range(len(args) / 2):
98 self._write(args[i * 2], args[i * 2 + 1])
99 else:
100 raise TypeError
102 def _remove(self, key):
103 path = self.prependPath(key)
104 return xshandle().rm(self.transaction, path)
106 def remove(self, *args):
107 """If no arguments are given, remove this transaction's path.
108 Otherwise, treat each argument as a subpath to this transaction's
109 path, and remove each of those instead.
110 """
111 if len(args) == 0:
112 xshandle().rm(self.transaction, self.path)
113 else:
114 for key in args:
115 self._remove(key)
117 def _list(self, key):
118 path = self.prependPath(key)
119 l = xshandle().ls(self.transaction, path)
120 if l:
121 return map(lambda x: key + "/" + x, l)
122 return []
124 def list(self, *args):
125 """If no arguments are given, list this transaction's path, returning
126 the entries therein, or the empty list if no entries are found.
127 Otherwise, treat each argument as a subpath to this transaction's
128 path, and return the cumulative listing of each of those instead.
129 """
130 if len(args) == 0:
131 ret = xshandle().ls(self.transaction, self.path)
132 if ret is None:
133 return []
134 else:
135 return ret
136 else:
137 ret = []
138 for key in args:
139 ret.extend(self._list(key))
140 return ret
143 def list_recursive_(self, subdir, keys):
144 ret = []
145 for key in keys:
146 new_subdir = subdir + "/" + key
147 l = xshandle().ls(self.transaction, new_subdir)
148 if l:
149 ret.append([key, self.list_recursive_(new_subdir, l)])
150 else:
151 ret.append([key, xshandle().read(self.transaction, new_subdir)])
152 return ret
155 def list_recursive(self, *args):
156 """If no arguments are given, list this transaction's path, returning
157 the entries therein, or the empty list if no entries are found.
158 Otherwise, treat each argument as a subpath to this transaction's
159 path, and return the cumulative listing of each of those instead.
160 """
161 if len(args) == 0:
162 args = self.list()
163 if args is None or len(args) == 0:
164 return []
166 return self.list_recursive_(self.path, args)
169 def gather(self, *args):
170 if len(args) and type(args[0]) != tuple:
171 args = args,
172 ret = []
173 for tup in args:
174 if len(tup) == 2:
175 (key, fn) = tup
176 defval = None
177 else:
178 (key, fn, defval) = tup
180 val = self._read(key)
181 # If fn is str, then this will successfully convert None to 'None'
182 # (which we don't want). If it is int or float, then it will
183 # throw ValueError on any non-convertible value. We check
184 # explicitly for None, using defval instead, but allow ValueError
185 # to propagate.
186 if val is None:
187 val = defval
188 else:
189 val = fn(val)
190 ret.append(val)
191 if len(ret) == 1:
192 return ret[0]
193 return ret
195 def store(self, *args):
196 if len(args) and type(args[0]) != tuple:
197 args = args,
198 for tup in args:
199 if len(tup) == 2:
200 (key, val) = tup
201 try:
202 fmt = { str : "%s",
203 int : "%i",
204 float : "%f",
205 long : "%li",
206 type(None) : None }[type(val)]
207 except KeyError:
208 raise TypeError
209 else:
210 (key, val, fmt) = tup
211 if val is None:
212 self._remove(key)
213 else:
214 self._write(key, fmt % val)
217 def mkdir(self, *args):
218 if len(args) == 0:
219 xshandle().mkdir(self.transaction, self.path)
220 else:
221 for key in args:
222 xshandle().mkdir(self.transaction, self.prependPath(key))
225 def get_permissions(self, *args):
226 """If no arguments are given, return the permissions at this
227 transaction's path. If one argument is given, treat that argument as
228 a subpath to this transaction's path, and return the permissions at
229 that path. Otherwise, treat each argument as a subpath to this
230 transaction's path, and return a list composed of the permissions at
231 each of those instead.
232 """
233 if len(args) == 0:
234 return xshandle().get_permissions(self.transaction, self.path)
235 if len(args) == 1:
236 return self._get_permissions(args[0])
237 ret = []
238 for key in args:
239 ret.append(self._get_permissions(key))
240 return ret
243 def _get_permissions(self, key):
244 path = self.prependPath(key)
245 try:
246 return xshandle().get_permissions(self.transaction, path)
247 except RuntimeError, ex:
248 raise RuntimeError(ex.args[0],
249 '%s, while getting permissions from %s' %
250 (ex.args[1], path))
253 def set_permissions(self, *args):
254 if len(args) == 0:
255 raise TypeError
256 elif isinstance(args[0], str):
257 self.callRebased(args[0], self.set_permissions, *args[1:])
258 else:
259 if not self.path:
260 raise RuntimeError('Cannot set permissions on the root')
262 xshandle().set_permissions(self.transaction, self.path,
263 list(args))
266 def remove2(self, middlePath, *args):
267 self.callRebased(middlePath, self.remove, *args)
270 def write2(self, middlePath, *args):
271 self.callRebased(middlePath, self.write, *args)
274 def callRebased(self, middlePath, func, *args):
275 oldpath = self.path
276 self.path = self.prependPath(middlePath)
277 try:
278 func(*args)
279 finally:
280 self.path = oldpath
283 def prependPath(self, key):
284 if self.path:
285 return self.path + '/' + key
286 else:
287 return key
290 def Read(cls, path, *args):
291 """If only one argument is given (path), return the value stored at
292 that path. If two arguments are given, treat the second argument as a
293 subpath within the first, and return the value at the composed path.
294 Otherwise, treat each argument after the first as a subpath to the
295 given path, and return a list composed of the values at each of those
296 instead. This operation is performed inside a transaction.
297 """
298 return complete(path, lambda t: t.read(*args))
299 Read = classmethod(Read)
301 def Write(cls, path, *args):
302 complete(path, lambda t: t.write(*args))
303 Write = classmethod(Write)
305 def Remove(cls, path, *args):
306 """If only one argument is given (path), remove it. Otherwise, treat
307 each further argument as a subpath to the given path, and remove each
308 of those instead. This operation is performed inside a transaction.
309 """
310 complete(path, lambda t: t.remove(*args))
311 Remove = classmethod(Remove)
313 def List(cls, path, *args):
314 """If only one argument is given (path), list its contents, returning
315 the entries therein, or the empty list if no entries are found.
316 Otherwise, treat each further argument as a subpath to the given path,
317 and return the cumulative listing of each of those instead. This
318 operation is performed inside a transaction.
319 """
320 return complete(path, lambda t: t.list(*args))
321 List = classmethod(List)
323 def ListRecursive(cls, path, *args):
324 """If only one argument is given (path), list its contents
325 recursively, returning the entries therein, or the empty list if no
326 entries are found. Otherwise, treat each further argument as a
327 subpath to the given path, and return the cumulative listing of each
328 of those instead. This operation is performed inside a transaction.
329 """
330 return complete(path, lambda t: t.list_recursive(*args))
331 ListRecursive = classmethod(ListRecursive)
333 def Gather(cls, path, *args):
334 return complete(path, lambda t: t.gather(*args))
335 Gather = classmethod(Gather)
337 def Store(cls, path, *args):
338 complete(path, lambda t: t.store(*args))
339 Store = classmethod(Store)
341 def SetPermissions(cls, path, *args):
342 complete(path, lambda t: t.set_permissions(*args))
343 SetPermissions = classmethod(SetPermissions)
345 def Mkdir(cls, path, *args):
346 complete(path, lambda t: t.mkdir(*args))
347 Mkdir = classmethod(Mkdir)
350 def complete(path, f):
351 while True:
352 t = xstransact(path)
353 try:
354 result = f(t)
355 if t.commit():
356 return result
357 except:
358 t.abort()
359 raise