Skip to content

Commit

Permalink
finish fleshing out OnIoDupSuber methods to better support keri escro…
Browse files Browse the repository at this point in the history
…ws for KELs
  • Loading branch information
SmithSamuelM committed Sep 10, 2024
1 parent 9f64bdf commit cadfa44
Show file tree
Hide file tree
Showing 4 changed files with 354 additions and 4 deletions.
172 changes: 172 additions & 0 deletions src/keri/db/dbing.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,65 @@ def delTopVal(self, db, top=b''):

# For subdbs the use keys with trailing part the is monotonically
# ordinal number serialized as 32 hex bytes

# used in OnSuberBase
def putOnVal(self, db, key, on=0, val=b'', *, sep=b'.'):
"""Write serialized bytes val to location at onkey consisting of
key + sep + serialized on in db.
Does not overwrite.
Returns:
result (bool): True if successful write i.e onkey not already in db
False otherwise
Parameters:
db (lmdbsubdb): named sub db of lmdb
key (bytes): key within sub db's keyspace plus trailing part on
on (int): ordinal number at which write
val (bytes): to be written at onkey
sep (bytes): separator character for split
"""
with self.env.begin(db=db, write=True, buffers=True) as txn:
if key: # not empty
onkey = onKey(key, on, sep=sep) # start replay at this enty 0 is earliest
else:
onkey = key
try:
return (txn.put(onkey, val, overwrite=False))
except lmdb.BadValsizeError as ex:
raise KeyError(f"Key: `{onkey}` is either empty, too big (for lmdb),"
" or wrong DUPFIXED size. ref) lmdb.BadValsizeError")

# used in OnSuberBase
def setOnVal(self, db, key, on=0, val=b'', *, sep=b'.'):
"""
Write serialized bytes val to location at onkey consisting of
key + sep + serialized on in db.
Overwrites pre-existing value at onkey if any.
Returns:
result (bool): True if successful write i.e onkey not already in db
False otherwise
Parameters:
db (lmdbsubdb): named sub db of lmdb
key (bytes): key within sub db's keyspace plus trailing part on
on (int): ordinal number at which write
val (bytes): to be written at onkey
sep (bytes): separator character for split
"""
with self.env.begin(db=db, write=True, buffers=True) as txn:
if key: # not empty
onkey = onKey(key, on, sep=sep) # start replay at this enty 0 is earliest
else:
onkey = key
try:
return (txn.put(onkey, val))
except lmdb.BadValsizeError as ex:
raise KeyError(f"Key: `{onkey}` is either empty, too big (for lmdb),"
" or wrong DUPFIXED size. ref) lmdb.BadValsizeError")


# used in OnSuberBase
def appendOnVal(self, db, key, val, *, sep=b'.'):
"""
Expand Down Expand Up @@ -721,6 +780,35 @@ def appendOnVal(self, db, key, val, *, sep=b'.'):
raise ValueError(f"Failed appending {val=} at {key=}.")
return on


# used in OnSuberBase
def getOnVal(self, db, key, on=0, *, sep=b'.'):
"""Gets value at onkey consisting of key + sep + serialized on in db.
Returns:
val (bytes | memoryview): entry at onkey consisting of key + sep +
serialized on in db.
None if no entry at key
Parameters:
db (lmdbsubdb): named sub db of lmdb
key (bytes): key within sub db's keyspace plus trailing part on
on (int): ordinal number at which to retrieve
sep (bytes): separator character for split
"""
with self.env.begin(db=db, write=False, buffers=True) as txn:
if key: # not empty
onkey = onKey(key, on, sep=sep) # start replay at this enty 0 is earliest
else:
onkey = key
try:
return(txn.get(onkey))
except lmdb.BadValsizeError as ex:
raise KeyError(f"Key: `{onkey}` is either empty, too big (for lmdb),"
" or wrong DUPFIXED size. ref) lmdb.BadValsizeError")


# used in OnSuberBase
def delOnVal(self, db, key, on=0, *, sep=b'.'):
"""
Expand Down Expand Up @@ -1713,6 +1801,34 @@ def getTopIoDupItemIter(self, db, top=b''):
# this is so we do the proem add and strip here not in some higher level class
# like suber

def addOnIoDupVal(self, db, key, on=0, val=b'', sep=b'.'):
"""
Add val bytes as dup at onkey consisting of key + sep + serialized on in db.
Adds to existing values at key if any
Returns True if written else False if dup val already exists
Duplicates are inserted in lexocographic order not insertion order.
Lmdb does not insert a duplicate unless it is a unique value for that
key.
Does inclusion test to dectect of duplicate already exists
Uses a python set for the duplicate inclusion test. Set inclusion scales
with O(1) whereas list inclusion scales with O(n).
Returns:
result (bool): True if duplicate val added at onkey idempotent
False if duplicate val preexists at onkey
Parameters:
db is opened named sub db with dupsort=True
key (bytes): key within sub db's keyspace plus trailing part on
val (bytes): serialized value to add at onkey as dup
sep (bytes): separator character for split
"""
onkey = onKey(key, on, sep=sep)
return (self.addIoDupVal(db, key=onkey, val=val))


# used in OnIoDupSuber
def appendOnIoDupVal(self, db, key, val, *, sep=b'.'):
"""
Expand Down Expand Up @@ -1742,6 +1858,62 @@ def appendOnIoDupVal(self, db, key, val, *, sep=b'.'):
return (self.appendOnVal(db=db, key=key, val=val, sep=sep))


def delOnIoDupVals(self, db, key, on=0, sep=b'.'):
"""Deletes all dup iovals at onkey consisting of key + sep + serialized
on in db.
Assumes DB opened with dupsort=True
Duplicates are inserted in lexocographic order not insertion order.
Lmdb does not insert a duplicate unless it is a unique value for that
key.
Does inclusion test to dectect of duplicate already exists
Uses a python set for the duplicate inclusion test. Set inclusion scales
with O(1) whereas list inclusion scales with O(n).
Returns:
result (bool): True if onkey present so all dups at onkey deleted
False if onkey not present
Parameters:
db is opened named sub db with dupsort=True
key (bytes): key within sub db's keyspace plus trailing part on
sep (bytes): separator character for split
"""
onkey = onKey(key, on, sep=sep)
return (self.delIoDupVals(db, key=onkey))


def delOnIoDupVal(self, db, key, on=0, val=b'', sep=b'.'):
"""Deletes dup ioval at key onkey consisting of key + sep + serialized
on in db.
Returns True if deleted else False if dup val not present
Assumes DB opened with dupsort=True
Duplicates are inserted in lexocographic order not insertion order.
Lmdb does not insert a duplicate unless it is a unique value for that
key.
Does inclusion test to dectect of duplicate already exists
Uses a python set for the duplicate inclusion test. Set inclusion scales
with O(1) whereas list inclusion scales with O(n).
Returns:
result (bool): True if duplicate val found and deleted
False if duplicate val does not exist at onkey
Parameters:
db is opened named sub db with dupsort=True
key (bytes): key within sub db's keyspace plus trailing part on
val (bytes): serialized dup value to del at onkey
sep (bytes): separator character for split
"""
onkey = onKey(key, on, sep=sep)
return (self.delIoDupVal(db, key=onkey, val=val))



# used in OnIoDupSuber
def getOnIoDupValIter(self, db, key=b'', on=0, *, sep=b'.'):
"""
Expand Down
124 changes: 121 additions & 3 deletions src/keri/db/subing.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,47 @@ def __init__(self, *pa, **kwa):
super(OnSuberBase, self).__init__(*pa, **kwa)


def putOn(self, keys: str | bytes | memoryview, on: int=0,
val: str | bytes | memoryview=''):
"""
Returns
result (bool): True if onkey made from key+sep+serialized on is
not found in database so value is written
idempotently.
False otherwise
Parameters:
keys (str | bytes | memoryview | Iterable): keys as prefix to be
combined with serialized on suffix and sep to form onkey
on (int): ordinal number used with onKey(key ,on) to form key.
val (str | bytes | memoryview): serialization
"""
return (self.db.putOnVal(db=self.sdb,
key=self._tokey(keys),
on=on,
val=self._ser(val),
sep=self.sep.encode()))

def pinOn(self, keys: str | bytes | memoryview, on: int=0,
val: str | bytes | memoryview=''):
"""
Returns
result (bool): True if value is written or overwritten at onkey
False otherwise
Parameters:
keys (str | bytes | memoryview | Iterable): keys as prefix to be
combined with serialized on suffix and sep to form onkey
on (int): ordinal number used with onKey(key ,on) to form key.
val (str | bytes | memoryview): serialization
"""
return (self.db.setOnVal(db=self.sdb,
key=self._tokey(keys),
on=on,
val=self._ser(val),
sep=self.sep.encode()))


def appendOn(self, keys: str | bytes | memoryview,
val: str | bytes | memoryview):
"""
Expand All @@ -446,14 +487,32 @@ def appendOn(self, keys: str | bytes | memoryview,
keys (str | bytes | memoryview | Iterable): top keys as prefix to be
combined with serialized on suffix and sep to form key
val (str | bytes | memoryview): serialization
on (int): ordinal number used with onKey(key,on) to form key.
"""
return (self.db.appendOnVal(db=self.sdb,
key=self._tokey(keys),
val=self._ser(val),
sep=self.sep.encode()))


def getOn(self, keys: str | bytes | memoryview, on: int=0):
"""
Returns
val (str): serialization at onkey if any
None if no entry at onkey
Parameters:
keys (str | bytes | memoryview | Iterable): keys as prefix to be
combined with serialized on suffix and sep to form onkey
on (int): ordinal number used with onKey(key ,on) to form key.
"""
val = self.db.getOnVal(db=self.sdb,
key=self._tokey(keys),
on=on,
sep=self.sep.encode())
return (self._des(val) if val is not None else None)



def remOn(self, keys: str | bytes | memoryview, on: int=0):
"""
Returns
Expand Down Expand Up @@ -2018,7 +2077,7 @@ def getLast(self, keys: str | bytes | memoryview | Iterable):


def rem(self, keys: str | bytes | memoryview | Iterable,
val: str | bytes | memoryview = b''):
val: str | bytes | memoryview = ''):
"""
Removes entry at key made from keys and dup val that matches val if any,
notwithstanding hidden ordinal proem. Otherwise deletes all dup values
Expand Down Expand Up @@ -2141,6 +2200,32 @@ def __init__(self, *pa, **kwa):
super(OnIoDupSuber, self).__init__(*pa, **kwa)


def addOn(self, keys: str | bytes | memoryview | Iterable, on: int=0,
val: str | bytes | memoryview = ''):
"""
Add val idempotently at key made from keys in insertion order using hidden
ordinal proem. Idempotently means do not add val that is already in
dup vals at key. Does not overwrite.
Parameters:
keys (str | bytes | memoryview | Iterable): top keys as prefix to be
combined with serialized on suffix and sep to form onkey
on (int): ordinal number used with onKey(pre,on) to form onkey.
val (str | bytes | memoryview): serialization
Returns:
result (bool): True means unique value added among duplications,
False means duplicate of same value already exists.
"""
return (self.db.addOnIoDupVal(db=self.sdb,
key=self._tokey(keys),
on=on,
val=self._ser(val),
sep=self.sep.encode()))



def appendOn(self, keys: str | bytes | memoryview,
val: str | bytes | memoryview):
"""
Expand All @@ -2151,13 +2236,46 @@ def appendOn(self, keys: str | bytes | memoryview,
keys (str | bytes | memoryview | Iterable): top keys as prefix to be
combined with serialized on suffix and sep to form key
val (str | bytes | memoryview): serialization
on (int): ordinal number used with onKey(pre,on) to form key.
"""
return (self.db.appendOnIoDupVal(db=self.sdb,
key=self._tokey(keys),
val=self._ser(val),
sep=self.sep.encode()))

def remOn(self, keys: str | bytes | memoryview | Iterable, on: int=0,
val: str | bytes | memoryview = ''):
"""
Removes entry at key made from keys and dup val that matches val if any,
notwithstanding hidden ordinal proem. Otherwise deletes all dup values
at key if any.
Parameters:
keys (str | bytes | memoryview | iterator): keys as prefix to be
combined with serialized on suffix and sep to form onkey
on (int): ordinal number used with onKey(pre,on) to form key.
val (str): value at key to delete. Subclass ._ser method may
accept different value types
if val is empty then remove all values at key
Returns:
result (bool): True if onkey with dup val exists so rem successful.
False otherwise
"""
if val:
return self.db.delOnIoDupVal(db=self.sdb,
key=self._tokey(keys),
on=on,
val=self._ser(val),
sep=self.sep.encode())
else:
return self.db.delOnIoDupVals(db=self.sdb,
key=self._tokey(keys),
on=on,
sep=self.sep.encode())



def getOnIter(self, keys: str|bytes|memoryview|Iterable = "", on: int=0):
"""
Expand Down
Loading

0 comments on commit cadfa44

Please sign in to comment.