public bool FindPreviousKey() { if (_currentKeyIndexInLeaf < 0) throw new BTDBException("Current Key is invalid"); if (_currentKeyIndex == _prefixKeyStart) return false; try { if (_currentKeyIndexInLeaf > 0) { _currentKeyIndexInLeaf--; _currentKeyIndex--; _owner.UpdateLastAccess(_currentKeySector); return true; } var sector = _currentKeySector; var parent = PopCurrentKeyParent(); while (parent != null) { var iter = new BTreeParentIterator(parent.Data); var childByPos = iter.FindChildByPos(sector.Position); if (childByPos == 0) { sector = parent; parent = PopCurrentKeyParent(); continue; } var childSectorPtr = iter.GetChildSectorPtr(childByPos - 1); while (true) { sector = LoadBTreeSector(childSectorPtr); if (sector.Type == SectorType.BTreeChild) { _currentKeyIndexInLeaf = (int)(BTreeChildIterator.CountFromSectorData(sector.Data) - 1); _currentKeyIndex--; return true; } iter = new BTreeParentIterator(sector.Data); childSectorPtr = iter.GetChildSectorPtr(iter.Count); } } throw new BTDBException("Internal error"); } catch { InvalidateCurrentKey(); throw; } }
void AddToBTreeParent(Sector leftSector, Sector rightSector, byte[] middleKeyData, int middleKeyLen, int middleKeyOfs, int middleKeyLenInSector) { var parentSector = leftSector.Parent; var iter = new BTreeParentIterator(parentSector.Data); int additionalLengthNeeded = BTreeParentIterator.HeaderForEntry + BTreeParentIterator.CalcEntrySize(middleKeyLen); int leftIndexInParent = iter.FindChildByPos(leftSector.Position); bool splitting = true; if (!KeyValueDB.ShouldSplitBTreeParent(iter.TotalLength, additionalLengthNeeded, iter.Count + 1)) { parentSector = _owner.ResizeSectorWithUpdatePositionNoWriteTruncate( parentSector, iter.TotalLength + additionalLengthNeeded, parentSector.Parent, _currentKeySectorParents); splitting = false; } var mergedData = new byte[iter.TotalLength + additionalLengthNeeded]; BTreeParentIterator.SetCountToSectorData(mergedData, iter.Count + 1); int ofs; int splitOfs = iter.OffsetOfIndex(leftIndexInParent); if (leftIndexInParent == 0) { SectorPtr.Pack(mergedData, BTreeParentIterator.FirstChildSectorPtrOffset, leftSector.ToSectorPtr()); PackUnpack.PackUInt64LE(mergedData, BTreeParentIterator.FirstChildSectorPtrOffset + KeyValueDB.PtrDownSize, CalcKeysInSector(leftSector)); ofs = BTreeParentIterator.HeaderSize + BTreeParentIterator.HeaderForEntry * (iter.Count + 1); } else { Array.Copy(iter.Data, BTreeParentIterator.FirstChildSectorPtrOffset, mergedData, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8); ofs = BTreeParentIterator.HeaderSize + BTreeParentIterator.HeaderForEntry * (iter.Count + 1); int splitOfsPrev = iter.OffsetOfIndex(leftIndexInParent - 1); Array.Copy(iter.Data, iter.FirstOffset, mergedData, ofs, splitOfsPrev - iter.FirstOffset); ofs += splitOfsPrev - iter.FirstOffset; Array.Copy(iter.Data, splitOfsPrev, mergedData, ofs, 4 + KeyValueDB.PtrDownSize); ofs += 4 + KeyValueDB.PtrDownSize; PackUnpack.PackUInt64LE(mergedData, ofs, CalcKeysInSector(leftSector)); ofs += 8; splitOfsPrev += 4 + KeyValueDB.PtrDownSize + 8; Array.Copy(iter.Data, splitOfsPrev, mergedData, ofs, splitOfs - splitOfsPrev); ofs += splitOfs - splitOfsPrev; } PackUnpack.PackInt32LE(mergedData, ofs, middleKeyLen); ofs += 4; SectorPtr.Pack(mergedData, ofs, rightSector.ToSectorPtr()); ofs += KeyValueDB.PtrDownSize; PackUnpack.PackUInt64LE(mergedData, ofs, CalcKeysInSector(rightSector)); ofs += 8; Array.Copy(middleKeyData, middleKeyOfs, mergedData, ofs, middleKeyLenInSector); ofs += middleKeyLenInSector; Array.Copy(iter.Data, splitOfs, mergedData, ofs, iter.TotalLength - splitOfs); BTreeParentIterator.RecalculateHeader(mergedData, iter.Count + 1); if (!splitting) { Array.Copy(mergedData, parentSector.Data, mergedData.Length); leftSector.Parent = parentSector; rightSector.Parent = parentSector; IncrementChildCountInBTreeParents(parentSector); _owner.FixChildrenParentPointers(parentSector); } else { iter = new BTreeParentIterator(mergedData); int middleoffset = mergedData.Length / 2; iter.MoveFirst(); int splitIndex = 0; int currentPos = iter.FirstOffset; while (currentPos < middleoffset) { currentPos += iter.CurrentEntrySize; splitIndex++; iter.MoveNext(); } Sector leftParentSector = null; Sector rightParentSector = null; try { rightParentSector = _owner.NewSector(); rightParentSector.Type = SectorType.BTreeParent; var rightCount = iter.Count - splitIndex - 1; var rightFirstOffset = BTreeParentIterator.HeaderSize + rightCount * BTreeParentIterator.HeaderForEntry; rightParentSector.SetLengthWithRound(rightFirstOffset + mergedData.Length - iter.NextEntryOffset); BTreeParentIterator.SetCountToSectorData(rightParentSector.Data, rightCount); rightParentSector.Parent = parentSector.Parent; var leftFirstOffset = BTreeParentIterator.HeaderSize + splitIndex * BTreeParentIterator.HeaderForEntry; leftParentSector = _owner.ResizeSectorWithUpdatePosition(parentSector, leftFirstOffset + currentPos - iter.FirstOffset, parentSector.Parent, _currentKeySectorParents); BTreeParentIterator.SetCountToSectorData(leftParentSector.Data, splitIndex); leftSector.Parent = leftParentSector; rightSector.Parent = leftParentSector; Array.Copy(mergedData, BTreeParentIterator.FirstChildSectorPtrOffset, leftParentSector.Data, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8 + BTreeParentIterator.HeaderForEntry * splitIndex); Array.Copy(mergedData, iter.FirstOffset, leftParentSector.Data, leftFirstOffset, currentPos - iter.FirstOffset); Array.Copy(mergedData, iter.ChildSectorPtrOffset, rightParentSector.Data, BTreeParentIterator.FirstChildSectorPtrOffset, KeyValueDB.PtrDownSize + 8); Array.Copy(mergedData, iter.NextEntryOffset, rightParentSector.Data, rightFirstOffset, iter.TotalLength - iter.NextEntryOffset); BTreeParentIterator.RecalculateHeader(rightParentSector.Data, rightCount); _owner.FixChildrenParentPointers(leftParentSector); _owner.PublishSector(rightParentSector, true); Interlocked.Increment(ref leftParentSector.ChildrenInCache); Interlocked.Increment(ref rightParentSector.ChildrenInCache); try { _owner.TruncateSectorCache(true, 0); int keyLenInSector = iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0); if (leftParentSector.Parent == null) { CreateBTreeParentFromTwoChildren(leftParentSector, rightParentSector, iter.Data, iter.KeyLen, iter.KeyOffset, keyLenInSector); } else { AddToBTreeParent(leftParentSector, rightParentSector, iter.Data, iter.KeyLen, iter.KeyOffset, keyLenInSector); } } finally { Interlocked.Decrement(ref leftParentSector.ChildrenInCache); Interlocked.Decrement(ref rightParentSector.ChildrenInCache); } } finally { if (leftSector.Parent == rightParentSector) { for (int i = 0; i < _currentKeySectorParents.Count; i++) { if (_currentKeySectorParents[i] == leftParentSector) { _currentKeySectorParents[i] = rightParentSector; break; } } } } } }
public bool FindNextKey() { if (_currentKeyIndexInLeaf < 0) throw new BTDBException("Current Key is invalid"); if (_prefixKeyCount != -1 && _currentKeyIndex + 1 >= _prefixKeyStart + _prefixKeyCount) return false; try { if (_currentKeyIndexInLeaf + 1 < BTreeChildIterator.CountFromSectorData(_currentKeySector.Data)) { _owner.UpdateLastAccess(_currentKeySector); _currentKeyIndexInLeaf++; if (CheckPrefix()) { _currentKeyIndex++; return true; } _prefixKeyCount = _currentKeyIndex - _prefixKeyStart + 1; _currentKeyIndexInLeaf--; return false; } var sector = _currentKeySector; var parent = PopCurrentKeyParent(); if (parent == null) { _prefixKeyCount = _currentKeyIndex - _prefixKeyStart + 1; FindLastKey(); return false; } while (true) { var iter = new BTreeParentIterator(parent.Data); var childByPos = iter.FindChildByPos(sector.Position); if (childByPos == iter.Count) { sector = parent; parent = PopCurrentKeyParent(); if (parent == null) { _prefixKeyCount = _currentKeyIndex - _prefixKeyStart + 1; FindLastKey(); return false; } continue; } var childSectorPtr = iter.GetChildSectorPtr(childByPos + 1); while (true) { sector = LoadBTreeSector(childSectorPtr); if (sector.Type == SectorType.BTreeChild) { _currentKeyIndexInLeaf = 0; _currentKeyIndex++; if (CheckPrefix()) { return true; } _prefixKeyCount = _currentKeyIndex - _prefixKeyStart; FindPreviousKey(); return false; } iter = new BTreeParentIterator(sector.Data); childSectorPtr = iter.GetChildSectorPtr(0); } } } catch { InvalidateCurrentKey(); throw; } }