示例#1
0
 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;
     }
 }
示例#2
0
 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;
                     }
                 }
             }
         }
     }
 }
示例#3
0
 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;
     }
 }