void CreateBTreeParentFromTwoLeafs(Sector leftSector, Sector rightSector) { var iter = new BTreeChildIterator(rightSector.Data); iter.MoveFirst(); int keyLenInSector = iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0); if (iter.HasKeySectorPtr) { ForceKeyFlush(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, rightSector); } CreateBTreeParentFromTwoChildren(leftSector, rightSector, iter.Data, iter.KeyLen, iter.KeyOffset, keyLenInSector); }
void EraseCompletely(ref Sector sector) { if (sector.Type == SectorType.BTreeChild) { var iter = new BTreeChildIterator(sector.Data); iter.MoveFirst(); do { if (iter.HasKeySectorPtr) DeleteContentSector(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, sector); if (iter.HasValueSectorPtr) DeleteContentSector(iter.ValueSectorPtr, iter.ValueLen - iter.ValueLenInline, sector); } while (iter.MoveNext()); } else { var iter = new BTreeParentIterator(sector.Data); for (int i = 0; i <= iter.Count; i++) { var childSectorPtr = iter.GetChildSectorPtr(i); var childSector = GetBTreeSector(childSectorPtr, sector); EraseCompletely(ref childSector); } } _owner.DeallocateSector(sector); sector = null; }
void SplitBTreeChild(byte[] keyBuf, int keyOfs, int keyLen, byte[] valueBuf, int valueOfs, int valueLen, Sector sector, BTreeChildIterator iter, int additionalLengthNeeded) { int middleoffset = (iter.TotalLength + iter.FirstOffset + additionalLengthNeeded) / 2; iter.MoveFirst(); bool beforeNew = true; int splitIndex = 0; int currentPos = iter.FirstOffset; while (currentPos < middleoffset) { if (beforeNew && splitIndex == _currentKeyIndexInLeaf) { beforeNew = false; currentPos += additionalLengthNeeded - BTreeChildIterator.HeaderForEntry; } else { currentPos += iter.CurrentEntrySize; splitIndex++; iter.MoveNext(); } } var rightSector = _owner.NewSector(); rightSector.Type = SectorType.BTreeChild; int rightCount = iter.Count - splitIndex + (beforeNew ? 1 : 0); rightSector.SetLengthWithRound(BTreeChildIterator.HeaderSize + rightCount * BTreeChildIterator.HeaderForEntry + iter.TotalLength + additionalLengthNeeded - BTreeChildIterator.HeaderForEntry - currentPos); BTreeChildIterator.SetCountToSectorData(rightSector.Data, rightCount); rightSector.Parent = sector.Parent; int leftCount = splitIndex + (beforeNew ? 0 : 1); var leftSector = _owner.ResizeSectorWithUpdatePosition(sector, BTreeChildIterator.HeaderSize + leftCount * BTreeChildIterator.HeaderForEntry + currentPos - iter.FirstOffset, sector.Parent, _currentKeySectorParents); _currentKeySector = leftSector; Sector newKeySector; BTreeChildIterator.SetCountToSectorData(leftSector.Data, leftCount); int newItemPos = iter.OffsetOfIndex(_currentKeyIndexInLeaf); int setActualDataPos; if (beforeNew) { Array.Copy(iter.Data, iter.FirstOffset, leftSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * leftCount, currentPos - iter.FirstOffset); Array.Copy(iter.Data, currentPos, rightSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * rightCount, newItemPos - currentPos); int rightPos = BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * rightCount + newItemPos - currentPos; setActualDataPos = rightPos; SetBTreeChildKeyDataJustLengths(rightSector, keyLen, valueLen, rightPos); rightPos += additionalLengthNeeded - BTreeChildIterator.HeaderForEntry; Array.Copy(iter.Data, newItemPos, rightSector.Data, rightPos, iter.TotalLength - newItemPos); newKeySector = rightSector; _currentKeyIndexInLeaf -= splitIndex; } else { Array.Copy(iter.Data, iter.FirstOffset, leftSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * leftCount, newItemPos - iter.FirstOffset); int leftPosInsert = BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * leftCount + newItemPos - iter.FirstOffset; int leftPos = leftPosInsert; leftPos += additionalLengthNeeded - BTreeChildIterator.HeaderForEntry; Array.Copy(iter.Data, currentPos - additionalLengthNeeded + BTreeChildIterator.HeaderForEntry, rightSector.Data, BTreeChildIterator.HeaderSize + BTreeChildIterator.HeaderForEntry * rightCount, iter.TotalLength + additionalLengthNeeded - BTreeChildIterator.HeaderForEntry - currentPos); Array.Copy(iter.Data, newItemPos, leftSector.Data, leftPos, currentPos - newItemPos - additionalLengthNeeded + BTreeChildIterator.HeaderForEntry); setActualDataPos = leftPosInsert; SetBTreeChildKeyDataJustLengths(leftSector, keyLen, valueLen, leftPosInsert); newKeySector = leftSector; } BTreeChildIterator.RecalculateHeader(leftSector.Data, leftCount); BTreeChildIterator.RecalculateHeader(rightSector.Data, rightCount); _owner.FixChildrenParentPointers(leftSector); _owner.PublishSector(rightSector, true); Interlocked.Increment(ref leftSector.ChildrenInCache); Interlocked.Increment(ref rightSector.ChildrenInCache); try { _owner.TruncateSectorCache(true, 0); SetBTreeChildKeyData(newKeySector, keyBuf, keyOfs, keyLen, valueBuf, valueOfs, valueLen, setActualDataPos); if (leftSector.Parent == null) { CreateBTreeParentFromTwoLeafs(leftSector, rightSector); } else { iter = new BTreeChildIterator(rightSector.Data); iter.MoveFirst(); if (iter.HasKeySectorPtr) ForceKeyFlush(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, rightSector); int keyLenInSector = iter.KeyLenInline + (iter.HasKeySectorPtr ? KeyValueDB.PtrDownSize : 0); AddToBTreeParent(leftSector, rightSector, iter.Data, iter.KeyLen, iter.KeyOffset, keyLenInSector); } } finally { Interlocked.Decrement(ref leftSector.ChildrenInCache); Interlocked.Decrement(ref rightSector.ChildrenInCache); } UnlockUselessAndFixKeySectorParents(newKeySector, leftSector, rightSector); _currentKeySector = newKeySector; }
void ExtractFirstKey(Sector sector, out byte[] data, out int ofs, out int len, out int keyLen) { if (sector.Type == SectorType.BTreeChild) { var iter = new BTreeChildIterator(sector.Data); iter.MoveFirst(); data = iter.Data; ofs = iter.KeyOffset; len = iter.ValueOffset - ofs; keyLen = iter.KeyLen; if (iter.HasKeySectorPtr) ForceKeyFlush(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline, sector); Debug.Assert(data == sector.Data); return; } else { var iter = new BTreeParentIterator(sector.Data); var childSector = GetBTreeSector(iter.FirstChildSectorPtr, sector); ExtractFirstKey(childSector, out data, out ofs, out len, out keyLen); } }
static int FindOfsInParent(Sector sector, Sector where) { switch (where.Type) { case SectorType.BTreeParent: { var iter = new BTreeParentIterator(where.Data); if ((iter.FirstChildSectorPos & MaskOfPosition) == sector.Position) return BTreeParentIterator.FirstChildSectorPtrOffset; if (iter.Count != 0) { iter.MoveFirst(); do { if ((iter.KeySectorPos & MaskOfPosition) == sector.Position) return iter.KeySectorPtrOffset; if ((iter.ChildSectorPos & MaskOfPosition) == sector.Position) return iter.ChildSectorPtrOffset; } while (iter.MoveNext()); } throw new BTDBException("Cannot FindOfsInParent"); } case SectorType.BTreeChild: { var iter = new BTreeChildIterator(where.Data); iter.MoveFirst(); do { if ((iter.KeySectorPos & MaskOfPosition) == sector.Position) return iter.KeySectorPtrOffset; if ((iter.ValueSectorPos & MaskOfPosition) == sector.Position) return iter.ValueSectorPtrOffset; } while (iter.MoveNext()); throw new BTDBException("Cannot FindOfsInParent"); } case SectorType.AllocParent: case SectorType.DataParent: for (int i = 0; i < where.Length / PtrDownSize; i++) { if ((PackUnpack.UnpackInt64LE(where.Data, i * PtrDownSize) & MaskOfPosition) == sector.Position) return i * PtrDownSize; } throw new BTDBException("Cannot FindOfsInParent"); case SectorType.DataChild: throw new BTDBException("DataChild cannot be parent"); case SectorType.AllocChild: throw new BTDBException("AllocChild cannot be parent"); default: throw new ArgumentOutOfRangeException(); } }
internal void FixChildrenParentPointers(Sector parent) { switch (parent.Type) { case SectorType.BTreeParent: { var iter = new BTreeParentIterator(parent.Data); for (int i = 0; i <= iter.Count; i++) { var childSectorPos = iter.GetChildSectorPos(i); FixChildParentPointer(childSectorPos, parent); } break; } case SectorType.BTreeChild: { var iter = new BTreeChildIterator(parent.Data); iter.MoveFirst(); do { if (iter.HasKeySectorPtr) FixChildParentPointer(iter.KeySectorPos, parent); if (iter.HasValueSectorPtr) FixChildParentPointer(iter.ValueSectorPos, parent); } while (iter.MoveNext()); break; } case SectorType.DataChild: case SectorType.AllocChild: break; case SectorType.AllocParent: case SectorType.DataParent: { var ptrCount = parent.Length / PtrDownSize; for (int i = 0; i < ptrCount; i++) { var sectorPos = PackUnpack.UnpackInt64LE(parent.Data, i * PtrDownSize); if (sectorPos == 0) break; FixChildParentPointer(sectorPos, parent); } } break; default: throw new InvalidOperationException(); } }
bool CheckBTree(SectorPtr sectorPtr) { byte[] sector = CheckSector(sectorPtr); if (sector == null) return false; if (BTreeChildIterator.IsChildFromSectorData(sector)) { var iter = new BTreeChildIterator(sector); iter.MoveFirst(); do { if (iter.HasKeySectorPtr) { if (!CheckDataPages(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline)) return false; } if (iter.HasValueSectorPtr) { if (!CheckDataPages(iter.ValueSectorPtr, iter.ValueLen - iter.ValueLenInline)) return false; } } while (iter.MoveNext()); } else { var iter = new BTreeParentIterator(sector); if (!CheckBTree(iter.FirstChildSectorPtr)) return false; iter.MoveFirst(); do { if (iter.HasKeySectorPtr) { if (!CheckDataPages(iter.KeySectorPtr, iter.KeyLen - iter.KeyLenInline)) return false; } if (!CheckBTree(iter.ChildSectorPtr)) return false; } while (iter.MoveNext()); } return true; }