self.abort()
return False
+def txnfun(envfun):
+ def fxf(fun):
+ def wrapper(self, *args, tx=None, **kwargs):
+ if tx is None:
+ while True:
+ try:
+ with txn(envfun(self)) as ltx:
+ ret = fun(self, *args, tx=ltx, **kwargs)
+ ltx.commit()
+ return ret
+ except deadlock:
+ continue
+ else:
+ return fun(self, *args, tx=tx, **kwargs)
+ return wrapper
+ return fxf
+
class database(object):
def __init__(self, env, name, create, mode):
self.env = env
continue
return ret
- def _nextseq(self, tx):
+ @txnfun(lambda self: self.env.env)
+ def _nextseq(self, *, tx):
if self.cf.has_key(b"seq", txn=tx.tx):
seq = struct.unpack(">Q", self.cf.get(b"seq", txn=tx.tx))[0]
else:
self.cf.put(b"seq", struct.pack(">Q", seq + 1), txn=tx.tx)
return seq
- def add(self, ob):
- while True:
- try:
- with txn(self.env.env) as tx:
- seq = self._nextseq(tx)
- self.ob.put(struct.pack(">Q", seq), ob, txn=tx.tx, flags=bd.DB_NOOVERWRITE)
- tx.commit()
- return seq
- except deadlock:
- continue
-
- def replace(self, id, ob):
- while True:
- try:
- with txn(self.env.env) as tx:
- key = struct.pack(">Q", id)
- if not self.ob.has_key(key, txn=tx.tx):
- raise KeyError(id)
- self.ob.put(key, ob, txn=tx.tx)
- tx.commit()
- return
- except deadlock:
- continue
+ @txnfun(lambda self: self.env.env)
+ def add(self, ob, *, tx):
+ seq = self._nextseq(tx=tx)
+ self.ob.put(struct.pack(">Q", seq), ob, txn=tx.tx, flags=bd.DB_NOOVERWRITE)
+ return seq
- def get(self, id):
- while True:
- try:
- return self.ob[struct.pack(">Q", id)]
- except KeyError:
- raise KeyError(id) from None
- except deadlock:
- continue
+ @txnfun(lambda self: self.env.env)
+ def replace(self, id, ob, *, tx):
+ key = struct.pack(">Q", id)
+ if not self.ob.has_key(key, txn=tx.tx):
+ raise KeyError(id)
+ self.ob.put(key, ob, txn=tx.tx)
+
+ @txnfun(lambda self: self.env.env)
+ def get(self, id, *, tx):
+ ret = self.ob.get(struct.pack(">Q", id), None)
+ if ret is None:
+ raise KeyError(id)
+ return ret
- def remove(self, id):
- while True:
- try:
- with txn(self.env.env) as tx:
- self.ob.delete(struct.pack(">Q", id), txn=tx.tx)
- tx.commit()
- return
- except deadlock:
- continue
+ @txnfun(lambda self: self.env.env)
+ def remove(self, id, *, tx):
+ key = struct.pack(">Q", id)
+ if not self.ob.has_key(key, txn=tx.tx):
+ raise KeyError(id)
+ self.ob.delete(key, txn=tx.tx)
import struct, contextlib
from . import db, lib
-from .db import bd
+from .db import bd, txnfun
deadlock = bd.DBLockDeadlockError
notfound = bd.DBNotFoundError
except deadlock:
continue
- def put(self, key, id):
- while True:
- try:
- with db.txn(self.db.env.env) as tx:
- obid = struct.pack(">Q", id)
- if not self.db.ob.has_key(obid, txn=tx.tx):
- raise ValueError("no such object in database: " + str(id))
- try:
- self.bk.put(self.typ.encode(key), obid, txn=tx.tx, flags=bd.DB_NODUPDATA)
- except bd.DBKeyExistError:
- return False
- tx.commit()
- return True
- except deadlock:
- continue
-
- def remove(self, key, id):
- while True:
+ @txnfun(lambda self: self.db.env.env)
+ def put(self, key, id, *, tx):
+ obid = struct.pack(">Q", id)
+ if not self.db.ob.has_key(obid, txn=tx.tx):
+ raise ValueError("no such object in database: " + str(id))
+ try:
+ self.bk.put(self.typ.encode(key), obid, txn=tx.tx, flags=bd.DB_NODUPDATA)
+ except bd.DBKeyExistError:
+ return False
+ return True
+
+ @txnfun(lambda self: self.db.env.env)
+ def remove(self, key, id, *, tx):
+ obid = struct.pack(">Q", id)
+ if not self.db.ob.has_key(obid, txn=tx.tx):
+ raise ValueError("no such object in database: " + str(id))
+ cur = self.bk.cursor(txn=tx.tx)
+ try:
try:
- with db.txn(self.db.env.env) as tx:
- obid = struct.pack(">Q", id)
- if not self.db.ob.has_key(obid, txn=tx.tx):
- raise ValueError("no such object in database: " + str(id))
- cur = self.bk.cursor(txn=tx.tx)
- try:
- try:
- cur.get_both(self.typ.encode(key), obid)
- except notfound:
- return False
- cur.delete()
- finally:
- cur.close()
- tx.commit()
- return True
- except deadlock:
- continue
+ cur.get_both(self.typ.encode(key), obid)
+ except notfound:
+ return False
+ cur.delete()
+ finally:
+ cur.close()
+ return True