📄 xbplustreebytes.py
字号:
import types, string, BufferFile, BplusTreeBytes, BplusTreeLong
from BplusTreeLong import BplusTreeException, BplusTreeBadKeyValue, BplusTreeKeyMissing, ENCODER, DECODER
def Initialize(treefilename, blockfilename, KeyLength,
CultureId=BplusTreeLong.INVARIANTCULTUREID,
nodesize=BplusTreeBytes.DEFAULTNODESIZE,
buffersize=BplusTreeBytes.DEFAULTBLOCKSIZE):
return BplusTreeBytes.Initialize(treefilename, blockfilename, KeyLength,
CultureId,nodesize,buffersize, initFunction=BplusTree)
def ReOpen(treefilename, blockfilename, access="r+b"):
return BplusTreeBytes.ReOpen(treefilename, blockfilename, access, initFunction=xBplusTreeBytes)
def ReadOnly(treefilename, blockfilename):
return BplusTreeBytes.ReadOnly(treefilename, blockfilename, initFunction=xBplusTreeBytes)
class xBplusTreeBytes(BplusTreeBytes.BplusTreeBytes):
BucketSizeLimit = -1
ByteGet = BplusTreeBytes.BplusTreeBytes.Get
ByteSet = BplusTreeBytes.BplusTreeBytes.Set
ByteRemove = BplusTreeBytes.BplusTreeBytes.RemoveKey
ByteFirstKey = BplusTreeBytes.BplusTreeBytes.FirstKey
ByteNextKey = BplusTreeBytes.BplusTreeBytes.NextKey
MaxPrefixLength = None
# use MaxKeyLength in place of prefix length
def LimitBucketSize(this, limit):
this.BucketSizeLimit = limit
def PrefixForByteCount(this, s, maxbytecount):
#print "maxbytecount is", maxbytecount
if len(s)<1:
return u"";
(bytes, count) = ENCODER(s)
while len(bytes)>maxbytecount:
s = s[:-1]
(bytes, count) = ENCODER(s)
return s
def FindBucketForPrefix(this, key, keyIsPrefix):
"returns (bucket or None, prefix)"
bucket = None
prefix = key
M = this.MaxPrefixLength
if M is None:
M = this.MaxPrefixLength = this.MaxKeyLen()
if not keyIsPrefix:
prefix = this.PrefixForByteCount(key, M)
bytes = this.ByteGet(prefix, None)
if bytes is not None:
bucket = xBucket(this)
bucket.Load(bytes)
if (bucket.Count()<1):
raise BplusTreeException, "empty bucket loaded"
return (bucket, prefix)
def RemoveKey(this, key):
(bucket, prefix) = this.FindBucketForPrefix(key, False)
if bucket is None:
raise BplusTreeKeyMissing, "no such key to delete "+repr(key)
bucket.Remove(key)
if bucket.Count()<1:
this.ByteRemove(prefix)
else:
this.ByteSet(prefix, bucket.dump())
def FirstKey(this):
prefix = this.ByteFirstKey()
if prefix is None:
return None
(bucket, dummy) = this.FindBucketForPrefix(prefix, True)
if bucket is None:
raise BplusTreeException, "byte tree gave bad first prefix"
return bucket.FirstKey()
def NextKey(this, AfterThisKey):
(bucket, prefix) = this.FindBucketForPrefix(AfterThisKey, False)
if bucket is not None:
result = bucket.NextKey(AfterThisKey)
if result is not None:
return result
# otherwise look in next bucket
nextprefix = this.ByteNextKey(prefix)
if nextprefix is None:
return None
(bucket, dummy) = this.FindBucketForPrefix(nextprefix, True)
return bucket.FirstKey()
def ContainsKey(this, key):
(bucket, prefix) = this.FindBucketForPrefix(key, False)
if bucket is None:
return False
test = bucket.Find(key)
if test is None:
return False
return True
def Get(this, key, defaultValue):
(bucket, prefix) = this.FindBucketForPrefix(key, False)
if bucket is not None:
test = bucket.Find(key)
if test is not None:
return test
return defaultValue
def __getitem__(this, key):
test = this.Get(key, None)
if test is None:
raise BplusTreeKeyMissing, "key not found "+key
return test
def __setitem__(this, key, value):
(bucket, prefix) = this.FindBucketForPrefix(key, False)
if bucket is None:
bucket = xBucket(this)
bucket.Add(key, value)
this.ByteSet(prefix, bucket.dump())
Set = __setitem__
class xBucket:
"bucket for elements with same prefix. Intended for small buckets"
def __init__(this, owner):
# owner not needed for python implementation?
this.BucketSizeLimit = owner.BucketSizeLimit
this.MaxKeyLen = owner.MaxKeyLen()
this.values = []
this.keys = []
def Count(this):
return len(this.keys)
def Load(this, serialization):
keys = this.keys
values = this.values
if len(keys)>0:
raise BplusTreeException, "cannot load into non-empty bucket"
index = 0
bytecount = len(serialization)
while index<bytecount:
keylength = BufferFile.RetrieveInt(serialization, index)
index += BufferFile.INTSTORAGE
nextindex = index+keylength
keybytes = serialization[index:nextindex]
index = nextindex
(key, dummy) = DECODER(keybytes)
valuelength = BufferFile.RetrieveInt(serialization, index)
index += BufferFile.INTSTORAGE
nextindex = index+valuelength
valuebytes = serialization[index:nextindex]
(value, dummy) = DECODER(valuebytes)
index = nextindex
keys.append(key)
values.append(value)
if index!=bytecount:
raise BplusTreeException, "error counting bytes "+repr((index,bytecount))
def dump(this):
allbytes = []
keys = this.keys
values = this.values
for index in xrange(len(this.keys)):
thisKey = keys[index]
thisValue = this.values[index]
keyPrefix = BufferFile.StoreInt(len(thisKey))
(keybytes, dummy) = ENCODER(thisKey)
allbytes.append(keyPrefix)
allbytes.append(keybytes)
valuePrefix = BufferFile.StoreInt(len(thisValue))
(valuebytes, dummy) = ENCODER(thisValue)
allbytes.append(valuePrefix)
allbytes.append(valuebytes)
#print allbytes
return string.join(allbytes, "")
def Add(this, key, map):
keys = this.keys
values = this.values
index = 0
limit = this.BucketSizeLimit
maxlen = len(this.keys)
while index<maxlen:
thiskey = keys[index]
thisvalue = values[index]
if thiskey==key:
keys[index] = key
value[index] = map
return
if thiskey>key:
values.insert(index, map)
keys.insert(index, key)
if limit>0 and len(this.keys)>limit:
raise BplusTreeException, "bucket size limit exceeded"
return
index += 1
keys.append(key)
values.append(map)
if limit>0 and len(this.keys)>limit:
raise BplusTreeException, "bucket size limit exceeded"
def Remove(this, key):
keys = this.keys
values = this.values
index = 0
maxlen = len(this.keys)
while index<maxlen:
thiskey = keys[index]
if thiskey==key:
del values[index]
del keys[index]
return
index+=1
raise BplusTreeKeyMissing, "no such key to delete "+repr(key)
def Find(this, key):
"return value found or None"
keys = this.keys
values = this.values
index = 0
maxlen = len(this.keys)
while index<maxlen:
thiskey = this.keys[index]
if thiskey==key:
return this.values[index]
index+=1
return None
def FirstKey(this):
if len(this.keys)<1:
return None
return this.keys[0]
def NextKey(this, AfterThisKey):
index = 0
keys = this.keys
maxlen = len(keys)
while index<maxlen:
thiskey = keys[index]
if thiskey>AfterThisKey:
return thiskey
index+=1
return None
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -