private PagerState CreateNewPagerState() { var mmf = MemoryMappedFile.CreateFromFile(_fileStream, Guid.NewGuid().ToString(), _fileStream.Length, MemoryMappedFileAccess.Read, null, HandleInheritability.None, true); MemoryMappedViewAccessor accessor; try { accessor = mmf.CreateViewAccessor(0, _fileStream.Length, MemoryMappedFileAccess.Read); } catch (Exception) { mmf.Dispose(); throw; } byte *p = null; accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref p); var newPager = new PagerState(this) { Accessor = accessor, Files = new[] { mmf }, MapBase = p }; newPager.AddRef(); // one for the pager return(newPager); }
private PagerState CreatePagerState() { var fileSize = GetFileSize(); var startingBaseAddressPtr = Syscall.mmap(IntPtr.Zero, (ulong)fileSize, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, _fd, 0); if (startingBaseAddressPtr.ToInt64() == -1) //system didn't succeed in mapping the address where we wanted { PosixHelper.ThrowLastError(Marshal.GetLastWin32Error()); } var allocationInfo = new PagerState.AllocationInfo { BaseAddress = (byte *)startingBaseAddressPtr.ToPointer(), Size = fileSize, MappedFile = null }; var newPager = new PagerState(this) { Files = null, // unused MapBase = allocationInfo.BaseAddress, AllocationInfos = new[] { allocationInfo } }; newPager.AddRef(); // one for the pager return(newPager); }
public override void AllocateMorePages(Transaction tx, long newLength) { if (newLength < _fileStream.Length) { throw new ArgumentException("Cannot set the legnth to less than the current length"); } if (newLength == _fileStream.Length) { return; } // need to allocate memory again NativeFileMethods.SetFileLength(_safeFileHandle, newLength); Debug.Assert(_fileStream.Length == newLength); PagerState.Release(); // when the last transaction using this is over, will dispose it PagerState newPager = CreateNewPagerState(); if (tx != null) // we only pass null during startup, and we don't need it there { newPager.AddRef(); // one for the current transaction tx.AddPagerState(newPager); } PagerState = newPager; NumberOfAllocatedPages = newLength / PageSize; }
public void SetPagerState(PagerState newState) { if (DisposeOnceRunner.Disposed) { ThrowAlreadyDisposedException(); } lock (_pagerStateModificationLocker) { newState.AddRef(); if (ShouldLockMemoryAtPagerLevel()) { // Note: This is handled differently in 32-bits. // Locking/unlocking the memory is done separately for each mapping. try { foreach (var info in newState.AllocationInfos) { if (info.Size == 0 || info.BaseAddress == null) { continue; } if (Sodium.sodium_mlock(info.BaseAddress, (UIntPtr)info.Size) != 0) { if (DoNotConsiderMemoryLockFailureAsCatastrophicError) { continue; // okay, can skip this, then } lock (WorkingSetIncreaseLocker) { // we should check ourselves again after we enter the lock, someone could halve already increased working set enough if (Sodium.sodium_mlock(info.BaseAddress, (UIntPtr)info.Size) != 0) { TryHandleFailureToLockMemory(info.BaseAddress, info.Size); } } } } } catch { // need to restore the state to the way it was, so we'll dispose the pager state newState.Release(); throw; } } _debugInfo = GetSourceName(); var oldState = _pagerState; _pagerState = newState; PagerStateChanged?.Invoke(newState); oldState?.Release(); } }
protected AbstractPager() { _increaseSize = MinIncreaseSize; MaxNodeSize = 1024; Debug.Assert((PageSize - Constants.PageHeaderSize) / Constants.MinKeysInPage >= 1024); PageMinSpace = (int)(PageMaxSpace * 0.33); PagerState = new PagerState(this); PagerState.AddRef(); }
public void SetPagerState(PagerState newState) { if (DisposeOnceRunner.Disposed) { ThrowAlreadyDisposedException(); } lock (_pagerStateModificationLocker) { newState.AddRef(); if (ShouldLockMemoryAtPagerLevel()) { // Note: This is handled differently in 32-bits. // Locking/unlocking the memory is done separately for each mapping. try { foreach (var info in newState.AllocationInfos) { if (info.Size == 0 || info.BaseAddress == null) { continue; } if (Sodium.sodium_mlock(info.BaseAddress, (UIntPtr)info.Size) != 0) { if (DoNotConsiderMemoryLockFailureAsCatastrophicError) { continue; // okay, can skip this, then } var sumOfAllocations = Bits.NextPowerOf2(newState.AllocationInfos.Sum(x => x.Size) * 2); if (TryHandleFailureToLockMemory(info.BaseAddress, info.Size, sumOfAllocations)) { break; } } } } catch { // need to restore the state to the way it was, so we'll dispose the pager state newState.Release(); throw; } } _debugInfo = GetSourceName(); var oldState = _pagerState; _pagerState = newState; PagerStateChanged?.Invoke(newState); oldState?.Release(); } }
public override void AllocateMorePages(Transaction tx, long newLength) { ThrowObjectDisposedIfNeeded(); var newLengthAfterAdjustment = NearestSizeToAllocationGranularity(newLength); if (newLengthAfterAdjustment < _totalAllocationSize) { throw new ArgumentException("Cannot set the legnth to less than the current length"); } if (newLengthAfterAdjustment == _totalAllocationSize) { return; } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; if (_totalAllocationSize + allocationSize >= long.MaxValue) //probably would never be true, but just in case { throw new OutOfMemoryException("failed to allocated more pages - reached maximum allowed space usage"); } _fileStream.SetLength(_totalAllocationSize + allocationSize); if (TryAllocateMoreContinuousPages(allocationSize) == false) { PagerState newPagerState = CreatePagerState(); if (newPagerState == null) { var errorMessage = string.Format( "Unable to allocate more pages - unsucsessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes", (_totalAllocationSize + allocationSize)); throw new OutOfMemoryException(errorMessage); } newPagerState.DebugVerify(newLengthAfterAdjustment); if (tx != null) { newPagerState.AddRef(); tx.AddPagerState(newPagerState); } var tmp = PagerState; PagerState = newPagerState; tmp.Release(); //replacing the pager state --> so one less reference for it } _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / PageSize; }
protected AbstractPager() { _increaseSize = MinIncreaseSize; // MaxNodeSize is usually persisted as an unsigned short. Therefore, we must ensure it is not possible to have an overflow. Debug.Assert(NodeMaxSize < ushort.MaxValue); Debug.Assert((PageSize - Constants.PageHeaderSize) / Constants.MinKeysInPage >= 1024); PageMinSpace = (int)(PageMaxSpace * 0.33); PagerState = new PagerState(this); PagerState.AddRef(); }
public override void AllocateMorePages(Transaction tx, long newLength) { var oldSize = NumberOfAllocatedPages * PageSize; if (newLength < oldSize) { throw new ArgumentException("Cannot set the legnth to less than the current length"); } if (newLength == oldSize) { return; // nothing to do } var increaseSize = (newLength - oldSize); NumberOfAllocatedPages += increaseSize / PageSize; var newPtr = Marshal.AllocHGlobal(new IntPtr(increaseSize)); var buffer = new Buffer { Handle = newPtr, Base = (byte *)newPtr.ToPointer(), Size = increaseSize }; _buffers = _buffers.Append(buffer); var newPager = new PagerState(this); newPager.AddRef(); // one for the pager if (tx != null) // we only pass null during startup, and we don't need it there { newPager.AddRef(); // one for the current transaction tx.AddPagerState(newPager); } PagerState.Release(); PagerState = newPager; }
public PureMemoryPager() { var ptr = Marshal.AllocHGlobal(MinIncreaseSize); var buffer = new Buffer { Handle = ptr, Base = (byte*)ptr.ToPointer(), Size = MinIncreaseSize }; _buffers.Append(buffer); NumberOfAllocatedPages = 0; PagerState.Release(); PagerState = new PagerState(this); PagerState.AddRef(); }
public void RefreshMappedView(Transaction tx) { PagerState newPagerState = CreatePagerState(); if (tx != null) { newPagerState.AddRef(); tx.AddPagerState(newPagerState); } var tmp = PagerState; PagerState = newPagerState; tmp.Release(); //replacing the pager state --> so one less reference for it }
public void SetPagerState(PagerState newState) { if (Disposed) { ThrowAlreadyDisposedException(); } lock (_pagerStateModificationLocker) { _debugInfo = GetSourceName(); var oldState = _pagerState; newState.AddRef(); _pagerState = newState; oldState?.Release(); } }
public PureMemoryPager() { var ptr = Marshal.AllocHGlobal(MinIncreaseSize); var buffer = new Buffer { Handle = ptr, Base = (byte *)ptr.ToPointer(), Size = MinIncreaseSize }; _buffers.Append(buffer); NumberOfAllocatedPages = 0; PagerState.Release(); PagerState = new PagerState(this); PagerState.AddRef(); }
public override void AllocateMorePages(Transaction tx, long newLength) { ThrowObjectDisposedIfNeeded(); var newLengthAfterAdjustment = NearestSizeToPageSize(newLength); if (newLengthAfterAdjustment < _totalAllocationSize) { throw new ArgumentException("Cannot set the length to less than the current length"); } if (newLengthAfterAdjustment == _totalAllocationSize) { return; } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; Syscall.ftruncate(_fd, (_totalAllocationSize + allocationSize)); if (TryAllocateMoreContinuousPages(allocationSize) == false) { PagerState newPagerState = CreatePagerState(); if (newPagerState == null) { var errorMessage = string.Format( "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes", (_totalAllocationSize + allocationSize)); throw new OutOfMemoryException(errorMessage); } newPagerState.DebugVerify(newLengthAfterAdjustment); if (tx != null) { newPagerState.AddRef(); tx.AddPagerState(newPagerState); } var tmp = PagerState; PagerState = newPagerState; tmp.Release(); //replacing the pager state --> so one less reference for it } _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / PageSize; }
private PagerState CreatePagerState() { var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length, _memoryMappedFileAccess, HandleInheritability.None, true); var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(); var mmFileAccessType = _access == Win32NativeFileAccess.GenericRead ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write; var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle, mmFileAccessType, 0, 0, UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row null); if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted { var innerException = new Win32Exception(); var errorMessage = string.Format( "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes", (_fileStream.Length)); throw new OutOfMemoryException(errorMessage, innerException); } var allocationInfo = new PagerState.AllocationInfo { BaseAddress = startingBaseAddressPtr, Size = _fileStream.Length, MappedFile = mmf }; var newPager = new PagerState(this) { Files = new[] { mmf }, MapBase = startingBaseAddressPtr, AllocationInfos = new[] { allocationInfo } }; newPager.AddRef(); // one for the pager return(newPager); }
public void SetPagerState(PagerState newState) { if (DisposeOnceRunner.Disposed) { ThrowAlreadyDisposedException(); } lock (_pagerStateModificationLocker) { newState.AddRef(); if (LockMemory) { try { foreach (var info in newState.AllocationInfos) { if (Sodium.sodium_mlock(info.BaseAddress, (UIntPtr)info.Size) != 0) { if (DoNotConsiderMemoryLockFailureAsCatastrophicError) { continue; // okay, can skip this, then } if (TryHandleFailureToLockMemory(newState, info)) { break; } } } } catch { // need to restore the state to the way it was, so we'll dispose the pager state newState.Release(); throw; } } _debugInfo = GetSourceName(); var oldState = _pagerState; _pagerState = newState; PagerStateChanged?.Invoke(newState); oldState?.Release(); } }
public PureMemoryPager(byte[] data) { var ptr = Marshal.AllocHGlobal(data.Length); var buffer = new Buffer { Handle = ptr, Base = (byte*)ptr.ToPointer(), Size = data.Length }; _buffers = _buffers.Append(buffer); NumberOfAllocatedPages = data.Length / PageSize; PagerState.Release(); PagerState = new PagerState(this); PagerState.AddRef(); fixed (byte* origin = data) { NativeMethods.memcpy(buffer.Base, origin, data.Length); } }
public void SetPagerState(PagerState newState) { if (DisposeOnceRunner.Disposed) { ThrowAlreadyDisposedException(); } lock (_pagerStateModificationLocker) { newState.AddRef(); if (ShouldLockMemoryAtPagerLevel()) { // Note: This is handled differently in 32-bits. // Locking/unlocking the memory is done separately for each mapping. try { foreach (var info in newState.AllocationInfos) { if (info.Size == 0 || info.BaseAddress == null) { continue; } Lock(info.BaseAddress, info.Size, state: null); } } catch { // need to restore the state to the way it was, so we'll dispose the pager state newState.Release(); throw; } } _debugInfo = GetSourceName(); var oldState = _pagerState; _pagerState = newState; PagerStateChanged?.Invoke(newState); oldState?.Release(); } }
public override void AllocateMorePages(Transaction tx, long newLength) { ThrowObjectDisposedIfNeeded(); var newLengthAfterAdjustment = NearestSizeToAllocationGranularity(newLength); if (newLengthAfterAdjustment <= _totalAllocationSize) { return; } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; Win32NativeFileMethods.SetFileLength(_handle, _totalAllocationSize + allocationSize); if (TryAllocateMoreContinuousPages(allocationSize) == false) { PagerState newPagerState = CreatePagerState(); if (newPagerState == null) { var errorMessage = string.Format( "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes", (_totalAllocationSize + allocationSize)); throw new OutOfMemoryException(errorMessage); } newPagerState.DebugVerify(newLengthAfterAdjustment); if (tx != null) { newPagerState.AddRef(); tx.AddPagerState(newPagerState); } var tmp = PagerState; PagerState = newPagerState; tmp.Release(); //replacing the pager state --> so one less reference for it } _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / PageSize; }
public override void AllocateMorePages(Transaction tx, long newLength) { ThrowObjectDisposedIfNeeded(); var newLengthAfterAdjustment = NearestSizeToPageSize(newLength); if (newLengthAfterAdjustment <= _totalAllocationSize) //nothing to do { return; } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; PosixHelper.AllocateFileSpace(_fd, (ulong)(_totalAllocationSize + allocationSize)); _totalAllocationSize += allocationSize; PagerState newPagerState = CreatePagerState(); if (newPagerState == null) { var errorMessage = string.Format( "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes", (_totalAllocationSize + allocationSize)); throw new OutOfMemoryException(errorMessage); } newPagerState.DebugVerify(newLengthAfterAdjustment); if (tx != null) { newPagerState.AddRef(); tx.AddPagerState(newPagerState); } var tmp = PagerState; PagerState = newPagerState; tmp.Release(); //replacing the pager state --> so one less reference for it NumberOfAllocatedPages = _totalAllocationSize / PageSize; }
public PureMemoryPager(byte[] data) { var ptr = Marshal.AllocHGlobal(data.Length); var buffer = new Buffer { Handle = ptr, Base = (byte *)ptr.ToPointer(), Size = data.Length }; _buffers = _buffers.Append(buffer); NumberOfAllocatedPages = data.Length / PageSize; PagerState.Release(); PagerState = new PagerState(this); PagerState.AddRef(); fixed(byte *origin = data) { NativeMethods.memcpy(buffer.Base, origin, data.Length); } }
private PagerState CreatePagerState() { var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length, _memoryMappedFileAccess, null, HandleInheritability.None, true); var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(); var mmFileAccessType = _access == NativeFileAccess.GenericRead ? MemoryMapNativeMethods.NativeFileMapAccessType.Read : MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.NativeFileMapAccessType.Write; var startingBaseAddressPtr = MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle, mmFileAccessType, 0, 0, UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row null); if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted { throw new Win32Exception(); } var allocationInfo = new PagerState.AllocationInfo { BaseAddress = startingBaseAddressPtr, Size = _fileStream.Length, MappedFile = mmf }; var newPager = new PagerState(this) { Files = new[] { mmf }, Accessor = null, //not available since MapViewOfFileEx is used (instead of MapViewOfFile - which is used in managed wrapper) MapBase = startingBaseAddressPtr, AllocationInfos = new[] { allocationInfo } }; newPager.AddRef(); // one for the pager return(newPager); }
private PagerState CreateNewPagerState() { MemoryMappedFileAccess memoryMappedFileAccess = _access == NativeFileAccess.GenericRead ? MemoryMappedFileAccess.Read : MemoryMappedFileAccess.ReadWrite; MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length, memoryMappedFileAccess, null, HandleInheritability.None, true); MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(0, _fileStream.Length, memoryMappedFileAccess); byte *p = null; accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref p); var newPager = new PagerState(this) { Accessor = accessor, Files = new[] { mmf }, MapBase = p }; newPager.AddRef(); // one for the pager return(newPager); }
private PagerState CreateInitialPagerState(long size, byte *requestedBaseAddress) { var allocationSize = NearestSizeToAllocationGranularity(size); var mmf = MemoryMappedFile.CreateNew(null, allocationSize, MemoryMappedFileAccess.ReadWrite); var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(); var startingBaseAddressPtr = MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle, MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.NativeFileMapAccessType.Write, 0, 0, UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row requestedBaseAddress); if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted { throw new Win32Exception(); } var allocationInfo = new PagerState.AllocationInfo { BaseAddress = startingBaseAddressPtr, Size = allocationSize, MappedFile = mmf }; var newPager = new PagerState(this) { Files = new[] { mmf }, Accessor = null, //not available since MapViewOfFileEx is used (instead of MapViewOfFile - which is used in managed wrapper) MapBase = startingBaseAddressPtr, AllocationInfos = new[] { allocationInfo } }; newPager.AddRef(); return(newPager); }
private PagerState CreatePagerState() { var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length, _memoryMappedFileAccess, null, HandleInheritability.None, true); var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(); var mmFileAccessType = _access == NativeFileAccess.GenericRead ? MemoryMapNativeMethods.NativeFileMapAccessType.Read : MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.NativeFileMapAccessType.Write; var startingBaseAddressPtr = MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle, mmFileAccessType, 0, 0, UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row null); if (startingBaseAddressPtr == (byte*)0) //system didn't succeed in mapping the address where we wanted throw new Win32Exception(); var allocationInfo = new PagerState.AllocationInfo { BaseAddress = startingBaseAddressPtr, Size = _fileStream.Length, MappedFile = mmf }; var newPager = new PagerState(this) { Files = new[] { mmf }, Accessor = null, //not available since MapViewOfFileEx is used (instead of MapViewOfFile - which is used in managed wrapper) MapBase = startingBaseAddressPtr, AllocationInfos = new[] { allocationInfo } }; newPager.AddRef(); // one for the pager return newPager; }
private PagerState CreateNewPagerState() { MemoryMappedFileAccess memoryMappedFileAccess = _access == NativeFileAccess.GenericRead ? MemoryMappedFileAccess.Read : MemoryMappedFileAccess.ReadWrite; MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length, memoryMappedFileAccess, null, HandleInheritability.None, true); MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(0, _fileStream.Length, memoryMappedFileAccess); byte* p = null; accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref p); var newPager = new PagerState(this) { Accessor = accessor, Files = new[] { mmf }, MapBase = p }; newPager.AddRef(); // one for the pager return newPager; }
private PagerState CreateNewPagerState() { var mmf = MemoryMappedFile.CreateFromFile(_fileStream, Guid.NewGuid().ToString(), _fileStream.Length, MemoryMappedFileAccess.Read, null, HandleInheritability.None, true); MemoryMappedViewAccessor accessor; try { accessor = mmf.CreateViewAccessor(0, _fileStream.Length, MemoryMappedFileAccess.Read); } catch (Exception) { mmf.Dispose(); throw; } byte* p = null; accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref p); var newPager = new PagerState(this) { Accessor = accessor, Files = new[] { mmf }, MapBase = p }; newPager.AddRef(); // one for the pager return newPager; }
private PagerState CreateInitialPagerState(long size, byte* requestedBaseAddress) { var allocationSize = NearestSizeToAllocationGranularity(size); var mmf = MemoryMappedFile.CreateNew(null, allocationSize, MemoryMappedFileAccess.ReadWrite); var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(); var startingBaseAddressPtr = MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle, MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.NativeFileMapAccessType.Write, 0, 0, UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row requestedBaseAddress); if (startingBaseAddressPtr == (byte*)0) //system didn't succeed in mapping the address where we wanted throw new Win32Exception(); var allocationInfo = new PagerState.AllocationInfo { BaseAddress = startingBaseAddressPtr, Size = allocationSize, MappedFile = mmf }; var newPager = new PagerState(this) { Files = new[] { mmf }, Accessor = null, //not available since MapViewOfFileEx is used (instead of MapViewOfFile - which is used in managed wrapper) MapBase = startingBaseAddressPtr, AllocationInfos = new[] { allocationInfo } }; newPager.AddRef(); return newPager; }
public override void AllocateMorePages(Transaction tx, long newLength) { var oldSize = NumberOfAllocatedPages * PageSize; if (newLength < oldSize) throw new ArgumentException("Cannot set the legnth to less than the current length"); if (newLength == oldSize) return; // nothing to do var increaseSize = (newLength - oldSize); NumberOfAllocatedPages += increaseSize / PageSize; var newPtr = Marshal.AllocHGlobal(new IntPtr(increaseSize)); var buffer = new Buffer { Handle = newPtr, Base = (byte*) newPtr.ToPointer(), Size = increaseSize }; _buffers = _buffers.Append(buffer); var newPager = new PagerState(this); newPager.AddRef(); // one for the pager if (tx != null) // we only pass null during startup, and we don't need it there { newPager.AddRef(); // one for the current transaction tx.AddPagerState(newPager); } PagerState.Release(); PagerState = newPager; }