Revision 30b46c1d pithos/backends/simple.py
b/pithos/backends/simple.py | ||
---|---|---|
44 | 44 |
|
45 | 45 |
logger = logging.getLogger(__name__) |
46 | 46 |
|
47 |
def backend_method(func=None, autocommit=1): |
|
48 |
if func is None: |
|
49 |
def fn(func): |
|
50 |
return backend_method(func, autocommit) |
|
51 |
return fn |
|
52 |
|
|
53 |
if not autocommit: |
|
54 |
return func |
|
55 |
def fn(self, *args, **kw): |
|
56 |
self.con.execute('begin deferred') |
|
57 |
try: |
|
58 |
ret = func(self, *args, **kw) |
|
59 |
self.con.commit() |
|
60 |
return ret |
|
61 |
except: |
|
62 |
self.con.rollback() |
|
63 |
raise |
|
64 |
return fn |
|
65 |
|
|
47 | 66 |
|
48 | 67 |
class SimpleBackend(BaseBackend): |
49 | 68 |
"""A simple backend. |
... | ... | |
110 | 129 |
'namelen': self.blocker.hashlen} |
111 | 130 |
self.mapper = Mapper(**params) |
112 | 131 |
|
132 |
@backend_method |
|
113 | 133 |
def get_account_meta(self, user, account, until=None): |
114 | 134 |
"""Return a dictionary with the account metadata.""" |
115 | 135 |
|
... | ... | |
146 | 166 |
meta.update({'until_timestamp': tstamp}) |
147 | 167 |
return meta |
148 | 168 |
|
169 |
@backend_method |
|
149 | 170 |
def update_account_meta(self, user, account, meta, replace=False): |
150 | 171 |
"""Update the metadata associated with the account.""" |
151 | 172 |
|
... | ... | |
154 | 175 |
raise NotAllowedError |
155 | 176 |
self._put_metadata(user, account, meta, replace, False) |
156 | 177 |
|
178 |
@backend_method |
|
157 | 179 |
def get_account_groups(self, user, account): |
158 | 180 |
"""Return a dictionary with the user groups defined for this account.""" |
159 | 181 |
|
... | ... | |
162 | 184 |
raise NotAllowedError |
163 | 185 |
return self._get_groups(account) |
164 | 186 |
|
187 |
@backend_method |
|
165 | 188 |
def update_account_groups(self, user, account, groups, replace=False): |
166 | 189 |
"""Update the groups associated with the account.""" |
167 | 190 |
|
... | ... | |
171 | 194 |
self._check_groups(groups) |
172 | 195 |
self._put_groups(account, groups, replace) |
173 | 196 |
|
197 |
@backend_method |
|
174 | 198 |
def put_account(self, user, account): |
175 | 199 |
"""Create a new account with the given name.""" |
176 | 200 |
|
... | ... | |
184 | 208 |
else: |
185 | 209 |
raise NameError('Account already exists') |
186 | 210 |
version_id = self._put_version(account, user) |
187 |
self.con.commit() |
|
188 | 211 |
|
212 |
@backend_method |
|
189 | 213 |
def delete_account(self, user, account): |
190 | 214 |
"""Delete the account with the given name.""" |
191 | 215 |
|
... | ... | |
198 | 222 |
sql = 'delete from versions where name = ?' |
199 | 223 |
self.con.execute(sql, (account,)) |
200 | 224 |
self._del_groups(account) |
201 |
self.con.commit() |
|
202 | 225 |
|
226 |
@backend_method |
|
203 | 227 |
def list_containers(self, user, account, marker=None, limit=10000, until=None): |
204 | 228 |
"""Return a list of containers existing under an account.""" |
205 | 229 |
|
... | ... | |
219 | 243 |
return containers[start:start + limit] |
220 | 244 |
return self._list_objects(account, '', '/', marker, limit, False, [], until) |
221 | 245 |
|
246 |
@backend_method |
|
222 | 247 |
def get_container_meta(self, user, account, container, until=None): |
223 | 248 |
"""Return a dictionary with the container metadata.""" |
224 | 249 |
|
... | ... | |
242 | 267 |
meta.update({'until_timestamp': tstamp}) |
243 | 268 |
return meta |
244 | 269 |
|
270 |
@backend_method |
|
245 | 271 |
def update_container_meta(self, user, account, container, meta, replace=False): |
246 | 272 |
"""Update the metadata associated with the container.""" |
247 | 273 |
|
... | ... | |
251 | 277 |
path, version_id, mtime = self._get_containerinfo(account, container) |
252 | 278 |
self._put_metadata(user, path, meta, replace, False) |
253 | 279 |
|
280 |
@backend_method |
|
254 | 281 |
def get_container_policy(self, user, account, container): |
255 | 282 |
"""Return a dictionary with the container policy.""" |
256 | 283 |
|
... | ... | |
260 | 287 |
path = self._get_containerinfo(account, container)[0] |
261 | 288 |
return self._get_policy(path) |
262 | 289 |
|
290 |
@backend_method |
|
263 | 291 |
def update_container_policy(self, user, account, container, policy, replace=False): |
264 | 292 |
"""Update the policy associated with the account.""" |
265 | 293 |
|
... | ... | |
275 | 303 |
for k, v in policy.iteritems(): |
276 | 304 |
sql = 'insert or replace into policy (name, key, value) values (?, ?, ?)' |
277 | 305 |
self.con.execute(sql, (path, k, v)) |
278 |
self.con.commit() |
|
279 | 306 |
|
307 |
@backend_method |
|
280 | 308 |
def put_container(self, user, account, container, policy=None): |
281 | 309 |
"""Create a new container with the given name.""" |
282 | 310 |
|
... | ... | |
299 | 327 |
for k, v in policy.iteritems(): |
300 | 328 |
sql = 'insert or replace into policy (name, key, value) values (?, ?, ?)' |
301 | 329 |
self.con.execute(sql, (path, k, v)) |
302 |
self.con.commit() |
|
303 | 330 |
|
331 |
@backend_method |
|
304 | 332 |
def delete_container(self, user, account, container, until=None): |
305 | 333 |
"""Delete/purge the container with the given name.""" |
306 | 334 |
|
... | ... | |
316 | 344 |
c = self.con.execute(sql, (path + '/%', until)) |
317 | 345 |
for v in [x[0] for x in c.fetchall()]: |
318 | 346 |
self._del_version(v) |
319 |
self.con.commit() |
|
320 | 347 |
return |
321 | 348 |
|
322 | 349 |
count = self._get_pathstats(path)[0] |
... | ... | |
328 | 355 |
self.con.execute(sql, (path,)) |
329 | 356 |
self._copy_version(user, account, account, True, False) # New account version (for timestamp update). |
330 | 357 |
|
358 |
@backend_method |
|
331 | 359 |
def list_objects(self, user, account, container, prefix='', delimiter=None, marker=None, limit=10000, virtual=True, keys=[], until=None): |
332 | 360 |
"""Return a list of objects existing under a container.""" |
333 | 361 |
|
... | ... | |
337 | 365 |
path, version_id, mtime = self._get_containerinfo(account, container, until) |
338 | 366 |
return self._list_objects(path, prefix, delimiter, marker, limit, virtual, keys, until) |
339 | 367 |
|
368 |
@backend_method |
|
340 | 369 |
def list_object_meta(self, user, account, container, until=None): |
341 | 370 |
"""Return a list with all the container's object meta keys.""" |
342 | 371 |
|
... | ... | |
350 | 379 |
c = self.con.execute(sql, (path + '/%',)) |
351 | 380 |
return [x[0] for x in c.fetchall()] |
352 | 381 |
|
382 |
@backend_method |
|
353 | 383 |
def get_object_meta(self, user, account, container, name, version=None): |
354 | 384 |
"""Return a dictionary with the object metadata.""" |
355 | 385 |
|
... | ... | |
367 | 397 |
meta.update({'modified': modified, 'modified_by': muser}) |
368 | 398 |
return meta |
369 | 399 |
|
400 |
@backend_method |
|
370 | 401 |
def update_object_meta(self, user, account, container, name, meta, replace=False): |
371 | 402 |
"""Update the metadata associated with the object.""" |
372 | 403 |
|
... | ... | |
375 | 406 |
path, version_id, muser, mtime, size = self._get_objectinfo(account, container, name) |
376 | 407 |
self._put_metadata(user, path, meta, replace) |
377 | 408 |
|
409 |
@backend_method |
|
378 | 410 |
def get_object_permissions(self, user, account, container, name): |
379 | 411 |
"""Return the path from which this object gets its permissions from,\ |
380 | 412 |
along with a dictionary containing the permissions.""" |
... | ... | |
384 | 416 |
path = self._get_objectinfo(account, container, name)[0] |
385 | 417 |
return self._get_permissions(path) |
386 | 418 |
|
419 |
@backend_method |
|
387 | 420 |
def update_object_permissions(self, user, account, container, name, permissions): |
388 | 421 |
"""Update the permissions associated with the object.""" |
389 | 422 |
|
... | ... | |
394 | 427 |
r, w = self._check_permissions(path, permissions) |
395 | 428 |
self._put_permissions(path, r, w) |
396 | 429 |
|
430 |
@backend_method |
|
397 | 431 |
def get_object_public(self, user, account, container, name): |
398 | 432 |
"""Return the public URL of the object if applicable.""" |
399 | 433 |
|
... | ... | |
404 | 438 |
return '/public/' + path |
405 | 439 |
return None |
406 | 440 |
|
441 |
@backend_method |
|
407 | 442 |
def update_object_public(self, user, account, container, name, public): |
408 | 443 |
"""Update the public status of the object.""" |
409 | 444 |
|
... | ... | |
412 | 447 |
path = self._get_objectinfo(account, container, name)[0] |
413 | 448 |
self._put_public(path, public) |
414 | 449 |
|
450 |
@backend_method |
|
415 | 451 |
def get_object_hashmap(self, user, account, container, name, version=None): |
416 | 452 |
"""Return the object's size and a list with partial hashes.""" |
417 | 453 |
|
... | ... | |
421 | 457 |
hashmap = self.mapper.map_retr(version_id) |
422 | 458 |
return size, [binascii.hexlify(x) for x in hashmap] |
423 | 459 |
|
460 |
@backend_method |
|
424 | 461 |
def update_object_hashmap(self, user, account, container, name, size, hashmap, meta={}, replace_meta=False, permissions=None): |
425 | 462 |
"""Create/update an object with the specified size and partial hashes.""" |
426 | 463 |
|
... | ... | |
446 | 483 |
self.con.execute(sql, (dest_version_id, k, v)) |
447 | 484 |
if permissions is not None: |
448 | 485 |
self._put_permissions(path, r, w) |
449 |
self.con.commit() |
|
450 | 486 |
|
487 |
@backend_method |
|
451 | 488 |
def copy_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None, src_version=None): |
452 | 489 |
"""Copy an object's data and metadata.""" |
453 | 490 |
|
... | ... | |
471 | 508 |
self.con.execute(sql, (dest_version_id, k, v)) |
472 | 509 |
if permissions is not None: |
473 | 510 |
self._put_permissions(dest_path, r, w) |
474 |
self.con.commit() |
|
475 | 511 |
|
512 |
@backend_method |
|
476 | 513 |
def move_object(self, user, account, src_container, src_name, dest_container, dest_name, dest_meta={}, replace_meta=False, permissions=None): |
477 | 514 |
"""Move an object's data and metadata.""" |
478 | 515 |
|
... | ... | |
480 | 517 |
self.copy_object(user, account, src_container, src_name, dest_container, dest_name, dest_meta, replace_meta, permissions, None) |
481 | 518 |
self.delete_object(user, account, src_container, src_name) |
482 | 519 |
|
520 |
@backend_method |
|
483 | 521 |
def delete_object(self, user, account, container, name, until=None): |
484 | 522 |
"""Delete/purge an object.""" |
485 | 523 |
|
... | ... | |
499 | 537 |
pass |
500 | 538 |
else: |
501 | 539 |
self._del_sharing(path) |
502 |
self.con.commit() |
|
503 | 540 |
return |
504 | 541 |
|
505 | 542 |
path = self._get_objectinfo(account, container, name)[0] |
506 | 543 |
self._put_version(path, user, 0, 1) |
507 | 544 |
self._del_sharing(path) |
508 | 545 |
|
546 |
@backend_method |
|
509 | 547 |
def list_versions(self, user, account, container, name): |
510 | 548 |
"""Return a list of all (version, version_timestamp) tuples for an object.""" |
511 | 549 |
|
... | ... | |
517 | 555 |
c = self.con.execute(sql, (path,)) |
518 | 556 |
return [(int(x[0]), int(x[1])) for x in c.fetchall()] |
519 | 557 |
|
558 |
@backend_method(autocommit=0) |
|
520 | 559 |
def get_block(self, hash): |
521 | 560 |
"""Return a block's data.""" |
522 | 561 |
|
... | ... | |
526 | 565 |
raise NameError('Block does not exist') |
527 | 566 |
return blocks[0] |
528 | 567 |
|
568 |
@backend_method(autocommit=0) |
|
529 | 569 |
def put_block(self, data): |
530 | 570 |
"""Create a block and return the hash.""" |
531 | 571 |
|
... | ... | |
533 | 573 |
hashes, absent = self.blocker.block_stor((data,)) |
534 | 574 |
return binascii.hexlify(hashes[0]) |
535 | 575 |
|
576 |
@backend_method(autocommit=0) |
|
536 | 577 |
def update_block(self, hash, data, offset=0): |
537 | 578 |
"""Update a known block and return the hash.""" |
538 | 579 |
|
... | ... | |
584 | 625 |
tstamp = int(time.time()) |
585 | 626 |
sql = 'insert into versions (name, user, tstamp, size, hide) values (?, ?, ?, ?, ?)' |
586 | 627 |
id = self.con.execute(sql, (path, user, tstamp, size, hide)).lastrowid |
587 |
self.con.commit() |
|
588 | 628 |
return str(id) |
589 | 629 |
|
590 | 630 |
def _copy_version(self, user, src_path, dest_path, copy_meta=True, copy_data=True, src_version=None): |
... | ... | |
608 | 648 |
# TODO: Copy properly. |
609 | 649 |
hashmap = self.mapper.map_retr(src_version_id) |
610 | 650 |
self.mapper.map_stor(dest_version_id, hashmap) |
611 |
self.con.commit() |
|
612 | 651 |
return src_version_id, dest_version_id |
613 | 652 |
|
614 | 653 |
def _get_versioninfo(self, account, container, name, until=None): |
... | ... | |
663 | 702 |
else: |
664 | 703 |
sql = 'insert or replace into metadata (version_id, key, value) values (?, ?, ?)' |
665 | 704 |
self.con.execute(sql, (dest_version_id, k, v)) |
666 |
self.con.commit() |
|
667 | 705 |
|
668 | 706 |
def _check_policy(self, policy): |
669 | 707 |
for k in policy.keys(): |
... | ... | |
762 | 800 |
if v: |
763 | 801 |
sql = 'insert into groups (account, gname, user) values (?, ?, ?)' |
764 | 802 |
self.con.executemany(sql, [(account, k, x) for x in v]) |
765 |
self.con.commit() |
|
766 | 803 |
|
767 | 804 |
def _del_groups(self, account): |
768 | 805 |
sql = 'delete from groups where account = ?' |
... | ... | |
812 | 849 |
self.con.executemany(sql, [(path, 'read', x) for x in r]) |
813 | 850 |
if w: |
814 | 851 |
self.con.executemany(sql, [(path, 'write', x) for x in w]) |
815 |
self.con.commit() |
|
816 | 852 |
|
817 | 853 |
def _get_public(self, path): |
818 | 854 |
sql = 'select name from public where name = ?' |
... | ... | |
828 | 864 |
else: |
829 | 865 |
sql = 'insert or replace into public (name) values (?)' |
830 | 866 |
self.con.execute(sql, (path,)) |
831 |
self.con.commit() |
|
832 | 867 |
|
833 | 868 |
def _del_sharing(self, path): |
834 | 869 |
sql = 'delete from permissions where name = ?' |
835 | 870 |
self.con.execute(sql, (path,)) |
836 | 871 |
sql = 'delete from public where name = ?' |
837 | 872 |
self.con.execute(sql, (path,)) |
838 |
self.con.commit() |
|
839 | 873 |
|
840 | 874 |
def _is_allowed(self, user, account, container, name, op='read'): |
841 | 875 |
if user == account: |
Also available in: Unified diff