Changed rbyd/btree namelookups to only compare raw bytes
This is a simplification of the rbyd/btree layers, but implies
behavioral changes to the mtree/mdir layers.
Instead of ordering by leb128 did + name:
82 02 61 61 61 < 81 04 62 62 62
(0x102, "aaa") (0x201, "bbb")
We now order by the raw encoding, lexicographically:
82 02 61 61 61 > 81 04 62 62 62
(0x102, "aaa") (0x201, "bbb")
This may be unintuitive, but note:
1. Files _within_ a directory are still ordered, since they share a did
prefix.
2. We don't really care about the relative ordering of dids, just
that they are unique. Changing the ordering at this level does not
interfere with any of our did-related functions.
3. The only thing we may care about is that the root, did=0, is the
first mtree entry. This is still true. No leb128 encoding is < 0x00
even after encoding.
The motivation for this change is to allow for other named-btrees in the
system that may used non-did-prefixed names. At least one of these makes
sense for a sort of "content-tree" (cksum -> data block mapping).
As a plus, this change makes it possible to compare names and do btree
namelookups without needing to decode the leb128 prefix. Although I'm
struggling a bit to figure out exactly where this is useful...
One downside, this ordering only works if dids are always stored in
their canonical encoding, that is, the smallest leb128 encoding possible
for a given did. I think this is a reasonable requirement for just our
dids.
Another downside is this did add a decent chunk of code.
I did try limiting the changes to lfsr_data_namecmp, but it didn't have
much impact. I guess most of the cost comes from the reworked
lfsr_data_cmp function, which, to be fair, is quite a bit more
complicated now (it now supports limited data<=>data comparisons):
code stack
before: 34148 2896
namecmp: 34324 (+0.5%) 2896 (+0.0%)
after: 34340 (+0.6%) 2896 (+0.0%)
This commit is contained in:
+23
-10
@@ -131,6 +131,18 @@ def fromleb128(data):
|
||||
return word, i+1
|
||||
return word, len(data)
|
||||
|
||||
def toleb128(word):
|
||||
data = []
|
||||
word &= 0xffffffff
|
||||
while True:
|
||||
b, word = word & 0x7f, word >> 7
|
||||
if word:
|
||||
data.append(b | 0x80)
|
||||
else:
|
||||
data.append(b | 0x00)
|
||||
break
|
||||
return bytes(data)
|
||||
|
||||
def fromtag(data):
|
||||
data = data.ljust(4, b'\0')
|
||||
tag = (data[0] << 8) | data[1]
|
||||
@@ -868,7 +880,7 @@ class Rbyd:
|
||||
return True, -1, 0, None
|
||||
|
||||
# lookup by name
|
||||
def namelookup(self, did, name):
|
||||
def namelookup(self, name):
|
||||
# binary search
|
||||
best = (False, -1, 0, 0)
|
||||
lower = 0
|
||||
@@ -882,16 +894,14 @@ class Rbyd:
|
||||
# treat vestigial names as a catch-all
|
||||
if ((tag == TAG_NAME and rid-(w-1) == 0)
|
||||
or (tag & 0xff00) != TAG_NAME):
|
||||
did_ = 0
|
||||
name_ = b''
|
||||
else:
|
||||
did_, d = fromleb128(data)
|
||||
name_ = data[d:]
|
||||
name_ = data
|
||||
|
||||
# bisect search space
|
||||
if (did_, name_) > (did, name):
|
||||
if name_ > name:
|
||||
upper = rid-(w-1)
|
||||
elif (did_, name_) < (did, name):
|
||||
elif name_ < name:
|
||||
lower = rid + 1
|
||||
|
||||
# keep track of best match
|
||||
@@ -903,12 +913,12 @@ class Rbyd:
|
||||
return best
|
||||
|
||||
# lookup by name with this rbyd as the btree root
|
||||
def btree_namelookup(self, f, block_size, did, name):
|
||||
def btree_namelookup(self, f, block_size, name):
|
||||
rbyd = self
|
||||
bid = 0
|
||||
|
||||
while True:
|
||||
found, rid, tag, w = rbyd.namelookup(did, name)
|
||||
found, rid, tag, w = rbyd.namelookup(name)
|
||||
done, rid_, tag_, w_, j, d, data, _ = rbyd.lookup(rid, TAG_STRUCT)
|
||||
|
||||
# found another branch
|
||||
@@ -925,6 +935,9 @@ class Rbyd:
|
||||
|
||||
# lookup by name with this rbyd as the mroot
|
||||
def mtree_namelookup(self, f, block_size, did, name):
|
||||
# concatenate did + name
|
||||
name = toleb128(did) + name
|
||||
|
||||
# have mtree?
|
||||
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
||||
if not done and rid == -1 and tag == TAG_MTREE:
|
||||
@@ -936,7 +949,7 @@ class Rbyd:
|
||||
|
||||
# lookup our name in the mtree
|
||||
mbid, tag_, mw, data = mtree.btree_namelookup(
|
||||
f, block_size, did, name)
|
||||
f, block_size, name)
|
||||
if tag_ != TAG_MDIR:
|
||||
return False, -1, 0, None, -1, 0, 0
|
||||
|
||||
@@ -960,7 +973,7 @@ class Rbyd:
|
||||
mdir = self
|
||||
|
||||
# lookup name in our mdir
|
||||
found, rid, tag, w = mdir.namelookup(did, name)
|
||||
found, rid, tag, w = mdir.namelookup(name)
|
||||
return found, mbid, mw, mdir, rid, tag, w
|
||||
|
||||
# iterate through a directory assuming this is the mtree root
|
||||
|
||||
Reference in New Issue
Block a user