예제 #1
0
 public void SetChildSectorPtrWithKeyCount(int index, SectorPtr childSectorPtr, long keyCount)
 {
     if (index == 0)
     {
         FirstChildSectorPtr = childSectorPtr;
         FirstChildKeyCount  = keyCount;
         return;
     }
     MoveTo(index - 1);
     ChildSectorPtr = childSectorPtr;
     ChildKeyCount  = keyCount;
 }
예제 #2
0
 void ForceKeyFlush(SectorPtr keySectorPtr, int keySize, Sector parent)
 {
     // Because parent of sector could be just one and we are going to point to same sector from 2 places it needs to be forcibly flushed
     ForceFlushContentSector(keySectorPtr, keySize, parent);
 }
예제 #3
0
 void ForceFlushContentSector(SectorPtr sectorPtr, long len, Sector parent)
 {
     var sector = _owner.TryGetSector(sectorPtr.Ptr, true, parent);
     if (len <= KeyValueDB.MaxLeafDataSectorSize)
     {
         if (sector == null) return;
         _owner.ForceFlushSector(sector);
         return;
     }
     int downPtrCount;
     long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(len, out downPtrCount);
     sector = sector ?? _owner.ReadSector(sectorPtr, true, SectorTypeInit.DataParent, parent);
     for (int i = 0; i < downPtrCount; i++)
     {
         var downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize);
         ForceFlushContentSector(downSectorPtr, Math.Min(len, bytesInDownLevel), sector);
         len -= bytesInDownLevel;
     }
     _owner.ForceFlushSector(sector);
 }
예제 #4
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 long AllocBitsInAlloc(int grans, ref SectorPtr sectorPtr, long totalGrans, ulong startInBytes, Sector parent)
 {
     long startGran;
     Sector sector;
     if (totalGrans <= MaxLeafAllocSectorGrans)
     {
         var longestFree = _freeSpaceAllocatorOptimizer.QueryLongestForGran(startInBytes);
         if (longestFree < grans) return -1;
         sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocChild, parent);
         int startGranSearch = 0;
         while (true)
         {
             startGran = BitArrayManipulation.IndexOfFirstHole(sector.Data, grans, startGranSearch);
             if (startGran < 0)
             {
                 if (sector.Length < MaxLeafAllocSectorSize)
                 {
                     var oldData = sector.Data;
                     sector = ResizeSectorNoUpdatePosition(sector, sector.Length + AllocationGranularity, sector.Parent, null);
                     Array.Copy(oldData, 0, sector.Data, 0, oldData.Length);
                     sectorPtr.Ptr = sector.Position;
                     continue;
                 }
                 _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1);
                 return -1;
             }
             ulong checkStartInBytes = startInBytes + (ulong)startGran * AllocationGranularity;
             ulong foundFreeInBytes = _spaceUsedByReadOnlyTransactions.FindFreeSizeAfter(checkStartInBytes, (ulong)grans * AllocationGranularity);
             if (checkStartInBytes == foundFreeInBytes) break;
             ulong newStartGranSearch = (foundFreeInBytes - startInBytes) / AllocationGranularity;
             if (newStartGranSearch > MaxLeafAllocSectorGrans)
             {
                 _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1);
                 return -1;
             }
             startGranSearch = (int)newStartGranSearch;
         }
         sector = DirtizeSector(sector, parent, null);
         BitArrayManipulation.SetBits(sector.Data, (int)startGran, grans);
         sectorPtr = sector.ToSectorPtr();
         return startGran;
     }
     int childSectors;
     long gransInChild = GetGransInDownLevel(totalGrans, out childSectors);
     sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocParent, parent);
     sector = DirtizeSector(sector, parent, null);
     sectorPtr = sector.ToSectorPtr();
     var i = 0;
     long startingGranOfChild;
     SectorPtr childSectorPtr;
     for (; i < childSectors - 1; i++)
     {
         startingGranOfChild = i * gransInChild;
         childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize);
         startGran = AllocBitsInAlloc(grans, ref childSectorPtr, gransInChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector);
         if (startGran < 0) continue;
         Debug.Assert(sector.Dirty);
         SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr);
         startGran += startingGranOfChild;
         return startGran;
     }
     startingGranOfChild = i * gransInChild;
     childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize);
     startGran = AllocBitsInAlloc(grans, ref childSectorPtr, totalGrans - startingGranOfChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector);
     if (startGran >= 0)
     {
         SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr);
         startGran += startingGranOfChild;
         return startGran;
     }
     int childSectors2;
     long gransInChild2 = GetGransInDownLevel(totalGrans - startingGranOfChild, out childSectors2);
     Sector newLeafSector;
     if (gransInChild / MaxChildren != gransInChild2)
     {
         Debug.Assert(childSectors2 == MaxChildren);
         var newParentSector = NewSector();
         newParentSector.Type = SectorType.AllocParent;
         newParentSector.SetLengthWithRound(2 * PtrDownSize);
         newParentSector.Parent = sector;
         newLeafSector = NewSector();
         newLeafSector.Type = SectorType.AllocChild;
         newLeafSector.SetLengthWithRound((grans + 7) / 8);
         newLeafSector.Parent = newParentSector;
         BitArrayManipulation.SetBits(newLeafSector.Data, 0, grans);
         SectorPtr.Pack(newParentSector.Data, 0, childSectorPtr);
         SectorPtr.Pack(newParentSector.Data, PtrDownSize, newLeafSector.ToSectorPtr());
         SectorPtr.Pack(sector.Data, i * PtrDownSize, newParentSector.ToSectorPtr());
         FixChildParentPointer(childSectorPtr.Ptr, newParentSector);
         PublishSector(newLeafSector, false);
         PublishSector(newParentSector, false);
         TruncateSectorCache(true, 0);
         return startingGranOfChild + gransInChild2 * MaxChildren;
     }
     if (childSectors == MaxChildren) return -1;
     if (sector.Length < (childSectors + 1) * PtrDownSize)
     {
         var oldData = sector.Data;
         var oldSector = sector;
         sector = ResizeSectorNoUpdatePosition(sector, (childSectors + 1) * PtrDownSize, sector.Parent, null);
         if (oldSector != sector)
         {
             sectorPtr = sector.ToSectorPtr();
             Array.Copy(oldData, 0, sector.Data, 0, oldData.Length);
             FixChildrenParentPointers(sector);
         }
     }
     newLeafSector = NewSector();
     newLeafSector.Type = SectorType.AllocChild;
     newLeafSector.SetLengthWithRound((grans + 7) / 8);
     newLeafSector.Parent = sector;
     BitArrayManipulation.SetBits(newLeafSector.Data, 0, grans);
     SectorPtr.Pack(sector.Data, childSectors * PtrDownSize, newLeafSector.ToSectorPtr());
     PublishSector(newLeafSector, false);
     TruncateSectorCache(true, 0);
     return gransInChild * childSectors;
 }
예제 #5
0
 int ApproximateLengthOfBTreeChild(SectorPtr childSectorPtr)
 {
     if (childSectorPtr.Ptr >= 0)
     {
         return (int)(childSectorPtr.Ptr & KeyValueDB.MaskOfGranLength) * KeyValueDB.AllocationGranularity;
     }
     Sector child = _owner.TryGetSector(childSectorPtr.Ptr, false, null);
     return child.Length;
 }
예제 #6
0
 void ResizeContentSectorChild(SectorPtr oldSectorPtr, int oldLength, int newLength, Sector parentSector, int ofsInParent, byte[] buf, int bufOfs)
 {
     var sector = _owner.GetOrReadSector(oldSectorPtr, true, SectorTypeInit.DataChild, parentSector);
     byte[] oldData = sector.Data;
     sector = _owner.ResizeSectorNoUpdatePosition(sector, newLength, parentSector, null);
     if (buf == null)
     {
         Array.Copy(oldData, 0, sector.Data, 0, Math.Min(oldLength, newLength));
     }
     else
     {
         Array.Copy(buf, bufOfs, sector.Data, 0, newLength);
     }
     SectorPtr.Pack(parentSector.Data, ofsInParent, sector.ToSectorPtr());
 }
예제 #7
0
 void RecursiveWriteValue(SectorPtr sectorPtr, long valueLen, long ofs, int len, byte[] buf, int bufOfs, Sector newParent, int ofsInParent)
 {
     if (ofs < 0) throw new ArgumentOutOfRangeException("ofs");
     if (ofs + len > valueLen) throw new ArgumentOutOfRangeException("ofs");
     var dataSector = GetOrReadDataSector(sectorPtr, valueLen, newParent);
     if (dataSector.Type == SectorType.DataChild)
     {
         Debug.Assert(valueLen <= dataSector.Length);
         dataSector = _owner.ResizeSectorNoUpdatePosition(dataSector, dataSector.Length, newParent, null); // DirtizeSector but without update position
         if (buf != null)
         {
             Array.Copy(buf, bufOfs, dataSector.Data, (int)ofs, len);
         }
         else
         {
             Array.Clear(dataSector.Data, (int)ofs, len);
         }
         SectorPtr.Pack(newParent.Data, ofsInParent, dataSector.ToSectorPtr());
         return;
     }
     dataSector = _owner.DirtizeSector(dataSector, newParent, null);
     SectorPtr.Pack(newParent.Data, ofsInParent, dataSector.ToSectorPtr());
     int downPtrCount;
     long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(valueLen, out downPtrCount);
     var i = (int)(ofs / bytesInDownLevel);
     while (i < downPtrCount)
     {
         long newofs = ofs - i * bytesInDownLevel;
         if (newofs + len <= 0) break;
         long downValueLen;
         if (i < downPtrCount - 1)
         {
             downValueLen = bytesInDownLevel;
         }
         else
         {
             downValueLen = valueLen % bytesInDownLevel;
             if (downValueLen == 0) downValueLen = bytesInDownLevel;
         }
         SectorPtr downSectorPtr = SectorPtr.Unpack(dataSector.Data, i * KeyValueDB.PtrDownSize);
         int newBufOfs = bufOfs;
         int newlen = len;
         if (newofs < 0)
         {
             newlen += (int)newofs;
             newBufOfs -= (int)newofs;
             newofs = 0;
         }
         if (downValueLen - newofs < newlen)
         {
             newlen = (int)(downValueLen - newofs);
         }
         RecursiveWriteValue(downSectorPtr, downValueLen, newofs, newlen, buf, newBufOfs, dataSector, i * KeyValueDB.PtrDownSize);
         i++;
     }
 }
예제 #8
0
 Sector LoadBTreeSector(SectorPtr sectorPtr)
 {
     Sector sector = _owner.GetOrReadSector(sectorPtr, IsWritting(), SectorTypeInit.BTreeChildOrParent, _currentKeySector);
     if (_currentKeySector != null) _currentKeySectorParents.Add(_currentKeySector);
     _currentKeySector = sector;
     return sector;
 }
예제 #9
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 internal Sector GetOrReadSector(SectorPtr sectorPtr, bool inWriteTransaction, SectorTypeInit typeInit, Sector parent)
 {
     return TryGetSector(sectorPtr.Ptr, inWriteTransaction, parent) ??
            ReadSector(sectorPtr, inWriteTransaction, typeInit, parent);
 }
예제 #10
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 void UnsetBitsInAlloc(long startGran, int grans, ref SectorPtr sectorPtr, long totalGrans, Sector parent)
 {
     Sector sector = TryGetSector(sectorPtr.Ptr, true, parent);
     if (totalGrans <= MaxLeafAllocSectorGrans)
     {
         if (sector == null)
         {
             sector = ReadSector(sectorPtr, true, SectorTypeInit.AllocChild, parent);
         }
         sector = DirtizeSector(sector, parent, null);
         BitArrayManipulation.UnsetBits(sector.Data, (int)startGran, grans);
         sectorPtr = sector.ToSectorPtr();
         return;
     }
     int childSectors;
     long gransInChild = GetGransInDownLevel(totalGrans, out childSectors);
     if (sector == null)
     {
         sector = ReadSector(sectorPtr, true, SectorTypeInit.AllocParent, parent);
     }
     sector = DirtizeSector(sector, parent, null);
     for (var i = (int)(startGran / gransInChild); i < childSectors; i++)
     {
         var startingGranOfChild = i * gransInChild;
         if (startGran + grans <= startingGranOfChild) break;
         var childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize);
         var currentStartGran = Math.Max(0, startGran - startingGranOfChild);
         UnsetBitsInAlloc(currentStartGran,
                          (int)(Math.Min(startGran + grans - startingGranOfChild, gransInChild) - currentStartGran),
                          ref childSectorPtr,
                          Math.Min(totalGrans - startingGranOfChild, gransInChild),
                          sector);
         SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr);
     }
     sectorPtr = sector.ToSectorPtr();
 }
예제 #11
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 byte[] CheckSector(SectorPtr sectorPtr)
 {
     if (sectorPtr.Ptr <= 0) return null;
     int size = (int)(sectorPtr.Ptr & MaskOfGranLength) + 1;
     size = size * AllocationGranularity;
     var sector = new byte[size];
     if (_positionLessStream.Read(sector, 0, size, (ulong)(sectorPtr.Ptr & MaskOfPosition)) != size)
     {
         return null;
     }
     Interlocked.Add(ref _totalBytesRead, size);
     if (sectorPtr.Checksum != 0 && Checksum.CalcFletcher32(sector, 0, (uint)size) != sectorPtr.Checksum)
     {
         return null;
     }
     return sector;
 }
예제 #12
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 bool CheckDataPages(SectorPtr sectorPtr, long dataLen)
 {
     byte[] sector = CheckSector(sectorPtr);
     if (sector == null) return false;
     if (dataLen <= MaxLeafDataSectorSize) return true;
     int downPtrCount;
     long bytesInDownLevel = GetBytesInDownLevel(dataLen, out downPtrCount);
     for (int i = 0; i < downPtrCount; i++)
     {
         if (!CheckDataPages(SectorPtr.Unpack(sector, i * PtrDownSize), Math.Min(dataLen, bytesInDownLevel)))
             return false;
         dataLen -= bytesInDownLevel;
     }
     return true;
 }
예제 #13
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 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;
 }
예제 #14
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 bool CheckAllocPages(SectorPtr sectorPtr, long grans)
 {
     byte[] sector = CheckSector(sectorPtr);
     if (sector == null) return false;
     if (grans <= MaxLeafAllocSectorGrans) return true;
     int childSectors;
     long gransInChild = GetGransInDownLevel(grans, out childSectors);
     for (int i = 0; i < childSectors; i++)
     {
         if (!CheckAllocPages(SectorPtr.Unpack(sector, i * PtrDownSize), Math.Min(grans, gransInChild)))
             return false;
         grans -= gransInChild;
     }
     return true;
 }
예제 #15
0
 Sector GetBTreeSector(SectorPtr childSectorPtr, Sector parent)
 {
     return _owner.GetOrReadSector(childSectorPtr, true, SectorTypeInit.BTreeChildOrParent, parent);
 }
예제 #16
0
 Sector GetOrReadDataSector(SectorPtr sectorPtr, long dataLen, Sector parent)
 {
     return _owner.GetOrReadSector(sectorPtr, IsWritting(), dataLen > KeyValueDB.MaxLeafDataSectorSize ? SectorTypeInit.DataParent : SectorTypeInit.DataChild, parent);
 }
예제 #17
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 internal Sector ReadSector(SectorPtr sectorPtr, bool inWriteTransaction, SectorTypeInit typeInit, Sector parent)
 {
     Debug.Assert(sectorPtr.Ptr > 0);
     return ReadSector(sectorPtr.Ptr & MaskOfPosition, (int)(sectorPtr.Ptr & MaskOfGranLength) + 1, sectorPtr.Checksum, inWriteTransaction, typeInit, parent);
 }
예제 #18
0
 void RecursiveReadOverflown(long ofs, SectorPtr dataSectorPtr, Sector parentOfSector, long dataLen, byte[] buf, ref int bufOfs, ref int len)
 {
     Sector dataSector = GetOrReadDataSector(dataSectorPtr, dataLen, parentOfSector);
     if (dataSector.Type == SectorType.DataChild)
     {
         var copyLen = Math.Min(len, (int)(dataSector.Length - ofs));
         Array.Copy(dataSector.Data, (int)ofs, buf, bufOfs, copyLen);
         len -= copyLen;
         bufOfs += copyLen;
         return;
     }
     int downPtrCount;
     long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(dataLen, out downPtrCount);
     var childIndex = (int)(ofs / bytesInDownLevel);
     ofs = ofs % bytesInDownLevel;
     while (childIndex < downPtrCount && len > 0)
     {
         long childDataLen;
         if (childIndex < downPtrCount - 1)
         {
             childDataLen = bytesInDownLevel;
         }
         else
         {
             childDataLen = dataLen % bytesInDownLevel;
             if (childDataLen == 0) childDataLen = bytesInDownLevel;
         }
         dataSectorPtr = SectorPtr.Unpack(dataSector.Data, childIndex * KeyValueDB.PtrDownSize);
         RecursiveReadOverflown(ofs, dataSectorPtr, dataSector, childDataLen, buf, ref bufOfs, ref len);
         ofs = 0;
         childIndex++;
     }
 }
예제 #19
0
 internal static void Pack(byte[] data, int offset, SectorPtr value)
 {
     PackUnpack.PackInt64LE(data, offset, value.Ptr);
     PackUnpack.PackUInt32LE(data, offset + 8, value.Checksum);
 }
예제 #20
0
 void ResizeContentSector(SectorPtr oldSectorPtr, long oldSize, Sector parentSector, int ofsInParent, long newSize, byte[] buf, int bufOfs)
 {
     Debug.Assert(oldSize != 0 && newSize != 0);
     if (oldSize == newSize)
     {
         if (buf != null)
         {
             RecursiveWriteValue(oldSectorPtr, newSize, 0, (int)newSize, buf, bufOfs, parentSector, ofsInParent);
             return;
         }
         SectorPtr.Pack(parentSector.Data, ofsInParent, oldSectorPtr);
         return;
     }
     int oldDownPtrCount;
     var oldBytesInDownLevel = KeyValueDB.GetBytesInDownLevel(oldSize, out oldDownPtrCount);
     int newDownPtrCount;
     var newBytesInDownLevel = KeyValueDB.GetBytesInDownLevel(newSize, out newDownPtrCount);
     Sector sector;
     if (oldBytesInDownLevel < newBytesInDownLevel)
     {
         sector = _owner.NewSector();
         sector.SetLengthWithRound(newDownPtrCount * KeyValueDB.PtrDownSize);
         sector.Parent = parentSector;
         sector.Type = SectorType.DataParent;
         SectorPtr.Pack(sector.Data, 0, oldSectorPtr);
         _owner.PublishSector(sector, true);
         SectorPtr.Pack(parentSector.Data, ofsInParent, sector.ToSectorPtr());
         Interlocked.Increment(ref sector.ChildrenInCache);
         try
         {
             _owner.TruncateSectorCache(true, oldSectorPtr.Ptr);
         }
         finally
         {
             Interlocked.Decrement(ref sector.ChildrenInCache);
         }
         ResizeContentSector(oldSectorPtr, oldSize, sector, 0, newBytesInDownLevel, buf, bufOfs);
         for (int i = 1; i < newDownPtrCount; i++)
         {
             long downLevelSize = Math.Min(newSize - i * newBytesInDownLevel, newBytesInDownLevel);
             if (buf != null)
                 CreateContentSector(buf, (int)(bufOfs + i * newBytesInDownLevel), (int)downLevelSize, sector, i * KeyValueDB.PtrDownSize);
             else
                 CreateContentSector(downLevelSize, sector, i * KeyValueDB.PtrDownSize);
         }
         return;
     }
     if (oldBytesInDownLevel > newBytesInDownLevel)
     {
         sector = _owner.GetOrReadSector(oldSectorPtr, true, SectorTypeInit.DataParent, parentSector);
         for (int i = 1; i < oldDownPtrCount; i++)
         {
             long downLevelSize = Math.Min(oldSize - i * oldBytesInDownLevel, oldBytesInDownLevel);
             DeleteContentSector(SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize), downLevelSize, sector);
         }
         _owner.DeallocateSector(sector);
         ResizeContentSector(SectorPtr.Unpack(sector.Data, 0), oldBytesInDownLevel, parentSector, ofsInParent, newSize, buf, bufOfs);
         return;
     }
     if (oldBytesInDownLevel == 1)
     {
         ResizeContentSectorChild(oldSectorPtr, oldDownPtrCount, newDownPtrCount, parentSector, ofsInParent, buf, bufOfs);
         return;
     }
     sector = _owner.GetOrReadSector(oldSectorPtr, true, SectorTypeInit.DataParent, parentSector);
     SectorPtr lastSectorPtr;
     long lastOffset;
     for (int i = newDownPtrCount; i < oldDownPtrCount; i++)
     {
         lastOffset = i * oldBytesInDownLevel;
         lastSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize);
         DeleteContentSector(lastSectorPtr, Math.Min(oldSize - lastOffset, oldBytesInDownLevel), sector);
     }
     var lastCommonPtrCount = Math.Min(oldDownPtrCount, newDownPtrCount) - 1;
     byte[] oldData = sector.Data;
     sector = _owner.ResizeSectorNoUpdatePosition(sector, newDownPtrCount * KeyValueDB.PtrDownSize, parentSector, null);
     var commonLength = (lastCommonPtrCount + 1) * KeyValueDB.PtrDownSize;
     Array.Copy(oldData, 0, sector.Data, 0, commonLength);
     Array.Clear(sector.Data, commonLength, sector.Data.Length - commonLength);
     SectorPtr.Pack(parentSector.Data, ofsInParent, sector.ToSectorPtr());
     _owner.FixChildrenParentPointers(sector);
     if (buf != null)
     {
         for (int i = 0; i < lastCommonPtrCount; i++)
         {
             lastSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize);
             lastOffset = i * newBytesInDownLevel;
             RecursiveWriteValue(lastSectorPtr, newBytesInDownLevel, 0, (int)newBytesInDownLevel, buf, (int)(bufOfs + lastOffset), sector, i * KeyValueDB.PtrDownSize);
         }
     }
     lastSectorPtr = SectorPtr.Unpack(sector.Data, lastCommonPtrCount * KeyValueDB.PtrDownSize);
     lastOffset = lastCommonPtrCount * newBytesInDownLevel;
     ResizeContentSector(lastSectorPtr, Math.Min(oldSize - lastOffset, oldBytesInDownLevel), sector,
                         lastCommonPtrCount * KeyValueDB.PtrDownSize,
                         Math.Min(newSize - lastOffset, newBytesInDownLevel), buf, (int)(bufOfs + lastOffset));
     for (int i = oldDownPtrCount; i < newDownPtrCount; i++)
     {
         lastOffset = i * newBytesInDownLevel;
         if (buf != null)
             CreateContentSector(buf, (int)(bufOfs + lastOffset),
                                 (int)Math.Min(newSize - lastOffset, newBytesInDownLevel), sector,
                                 i * KeyValueDB.PtrDownSize);
         else
             CreateContentSector(Math.Min(newSize - lastOffset, newBytesInDownLevel), sector,
                                 i * KeyValueDB.PtrDownSize);
     }
 }
예제 #21
0
파일: SectorPtr.cs 프로젝트: quyenbc/BTDB
 internal static void Pack(byte[] data, int offset, SectorPtr value)
 {
     PackUnpack.PackInt64LE(data, offset, value.Ptr);
     PackUnpack.PackUInt32LE(data, offset + 8, value.Checksum);
 }
예제 #22
0
 int SectorDataCompare(int startOfs, byte[] buf, int ofs, int len, SectorPtr sectorPtr, int dataLen, Sector parent)
 {
     var sector = GetOrReadDataSector(sectorPtr, dataLen, parent);
     if (sector.Type == SectorType.DataChild)
     {
         int dataOfs = 0;
         if (startOfs < _prefix.Length)
         {
             int compareLen = Math.Min(_prefix.Length - startOfs, sector.Length);
             int res = BitArrayManipulation.CompareByteArray(_prefix, startOfs, compareLen, sector.Data, dataOfs,
                                                             compareLen);
             if (res != 0) return res;
             startOfs += compareLen;
             if (startOfs < _prefix.Length) return 0;
             dataOfs += compareLen;
         }
         if (ofs == -1) return 1;
         startOfs -= _prefix.Length;
         return BitArrayManipulation.CompareByteArray(buf,
                                                      ofs + startOfs,
                                                      Math.Min(len - startOfs, sector.Length - dataOfs),
                                                      sector.Data,
                                                      dataOfs,
                                                      sector.Length - dataOfs);
     }
     int downPtrCount;
     var bytesInDownLevel = (int)KeyValueDB.GetBytesInDownLevel(dataLen, out downPtrCount);
     int i;
     SectorPtr downSectorPtr;
     for (i = 0; i < downPtrCount - 1; i++)
     {
         downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize);
         int res = SectorDataCompare(startOfs,
                                     buf,
                                     ofs,
                                     len,
                                     downSectorPtr,
                                     Math.Min(dataLen, bytesInDownLevel),
                                     sector);
         if (res != 0) return res;
         startOfs += bytesInDownLevel;
         dataLen -= bytesInDownLevel;
     }
     downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize);
     return SectorDataCompare(startOfs, buf, ofs, len, downSectorPtr, dataLen, sector);
 }
예제 #23
0
 public void SetChildSectorPtrWithKeyCount(int index, SectorPtr childSectorPtr, long keyCount)
 {
     if (index == 0)
     {
         FirstChildSectorPtr = childSectorPtr;
         FirstChildKeyCount = keyCount;
         return;
     }
     MoveTo(index - 1);
     ChildSectorPtr = childSectorPtr;
     ChildKeyCount = keyCount;
 }
예제 #24
0
 void DeleteContentSector(SectorPtr sectorPtr, long len, Sector parent)
 {
     var sector = GetOrReadDataSector(sectorPtr, len, parent);
     if (sector.Type == SectorType.DataChild)
     {
         _owner.DeallocateSector(sector);
         return;
     }
     int downPtrCount;
     long bytesInDownLevel = KeyValueDB.GetBytesInDownLevel(len, out downPtrCount);
     for (int i = 0; i < downPtrCount; i++)
     {
         var downSectorPtr = SectorPtr.Unpack(sector.Data, i * KeyValueDB.PtrDownSize);
         DeleteContentSector(downSectorPtr, Math.Min(len, bytesInDownLevel), sector);
         len -= bytesInDownLevel;
     }
     _owner.DeallocateSector(sector);
 }
예제 #25
0
파일: KeyValueDB.cs 프로젝트: quyenbc/BTDB
 long AllocBitsInAlloc(int grans, ref SectorPtr sectorPtr, long totalGrans, ulong startInBytes, Sector parent, long startSearchInGrans)
 {
     Sector sector;
     long startGran;
     if (totalGrans <= MaxLeafAllocSectorGrans)
     {
         var longestFree = _freeSpaceAllocatorOptimizer.QueryLongestForGran(startInBytes);
         if (longestFree < grans) return -1;
         sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocChild, parent);
         int startGranSearch = 0;
         while (true)
         {
             startGran = BitArrayManipulation.IndexOfFirstHole(sector.Data, grans, startGranSearch);
             if (startGran < 0)
             {
                 if (sector.Length == MaxLeafAllocSectorSize)
                 {
                     _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1);
                 }
                 return -1;
             }
             ulong checkStartInBytes = startInBytes + (ulong)startGran * AllocationGranularity;
             ulong foundFreeInBytes = _spaceUsedByReadOnlyTransactions.FindFreeSizeAfter(checkStartInBytes, (ulong)grans * AllocationGranularity);
             if (checkStartInBytes == foundFreeInBytes) break;
             ulong newStartGranSearch = (foundFreeInBytes - startInBytes) / AllocationGranularity;
             if (newStartGranSearch > MaxLeafAllocSectorGrans)
             {
                 _freeSpaceAllocatorOptimizer.UpdateLongestForGran(startInBytes, grans - 1);
                 return -1;
             }
             startGranSearch = (int)newStartGranSearch;
         }
         sector = DirtizeSector(sector, sector.Parent, null);
         BitArrayManipulation.SetBits(sector.Data, (int)startGran, grans);
         sectorPtr = sector.ToSectorPtr();
         return startGran;
     }
     int childSectors;
     long gransInChild = GetGransInDownLevel(totalGrans, out childSectors);
     sector = GetOrReadSector(sectorPtr, true, SectorTypeInit.AllocParent, parent);
     sector = DirtizeSector(sector, parent, null);
     sectorPtr = sector.ToSectorPtr();
     var i = 0;
     long startingGranOfChild;
     SectorPtr childSectorPtr;
     if (startSearchInGrans > 0)
     {
         i = (int)(startSearchInGrans / gransInChild);
         Debug.Assert(i < childSectors);
     }
     for (; i < childSectors - 1; i++)
     {
         startingGranOfChild = i * gransInChild;
         childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize);
         startGran = AllocBitsInAlloc(grans, ref childSectorPtr, gransInChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector, startSearchInGrans - startingGranOfChild);
         if (startGran < 0) continue;
         Debug.Assert(sector.Dirty);
         SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr);
         startGran += startingGranOfChild;
         return startGran;
     }
     startingGranOfChild = i * gransInChild;
     childSectorPtr = SectorPtr.Unpack(sector.Data, i * PtrDownSize);
     startGran = AllocBitsInAlloc(grans, ref childSectorPtr, totalGrans - startingGranOfChild, startInBytes + (ulong)(i * gransInChild * AllocationGranularity), sector, startSearchInGrans - startingGranOfChild);
     if (startGran >= 0)
     {
         SectorPtr.Pack(sector.Data, i * PtrDownSize, childSectorPtr);
         startGran += startingGranOfChild;
         return startGran;
     }
     return -1;
 }