-import struct, contextlib
+import struct, contextlib, math
from . import db, lib
-from .db import bd
+from .db import bd, txnfun
+
+__all__ = ["maybe", "t_int", "t_uint", "t_float", "t_str", "ordered"]
deadlock = bd.DBLockDeadlockError
notfound = bd.DBNotFoundError
else:
return self.bk.compare(a[1:], b[1:])
-t_int = simpletype.struct(">Q")
+def floatcmp(a, b):
+ if math.isnan(a) and math.isnan(b):
+ return 0
+ elif math.isnan(a):
+ return -1
+ elif math.isnan(b):
+ return 1
+ elif a < b:
+ return -1
+ elif a > b:
+ return 1
+ else:
+ return 0
+
+t_int = simpletype.struct(">q")
+t_uint = simpletype.struct(">Q")
+t_float = simpletype.struct(">d")
+t_float.compare = floatcmp
+t_str = simpletype((lambda ob: ob.encode("utf-8")), (lambda dat: dat.decode("utf-8")))
class index(object):
def __init__(self, db, name, datatype):
missing = object()
class ordered(index, lib.closable):
- def __init__(self, db, name, datatype, duplicates, create=True):
+ def __init__(self, db, name, datatype, create=True):
super().__init__(db, name, datatype)
- self.dup = duplicates
fl = bd.DB_THREAD | bd.DB_AUTO_COMMIT
if create: fl |= bd.DB_CREATE
def initdb(db):
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