private void WriteFile(long position, byte *p, int numberOfPages) { _nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); _nativeOverlapped->OffsetHigh = (int)(position >> 32); _nativeOverlapped->EventHandle = IntPtr.Zero; Debug.Assert(_options.IoMetrics != null); bool writeSuccess; var nNumberOfBytesToWrite = numberOfPages * _options.PageSize; using (_options.IoMetrics.MeterIoRate(_filename, IoMetrics.MeterType.JournalWrite, nNumberOfBytesToWrite)) { int written; writeSuccess = Win32NativeFileMethods.WriteFile(_handle, p, nNumberOfBytesToWrite, out written, _nativeOverlapped); } if (writeSuccess == false) { throw new IOException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } }
public Win32FileJournalWriter(StorageEnvironmentOptions options, string filename, long journalSize) { _options = options; _filename = filename; _handle = Win32NativeFileMethods.CreateFile(filename, Win32NativeFileAccess.GenericWrite, Win32NativeFileShare.Read, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, options.WinOpenFlags, IntPtr.Zero); if (_handle.IsInvalid) { throw new IOException("When opening file " + filename, new Win32Exception(Marshal.GetLastWin32Error())); } _maxNumberOfPagesPerSingleWrite = int.MaxValue / _options.PageSize; Win32NativeFileMethods.SetFileLength(_handle, journalSize); NumberOfAllocatedPages = (int)(journalSize / _options.PageSize); _nativeOverlapped = (NativeOverlapped *)NativeMemory.AllocateMemory(sizeof(NativeOverlapped)); _nativeOverlapped->InternalLow = IntPtr.Zero; _nativeOverlapped->InternalHigh = IntPtr.Zero; }
public Win32FileJournalWriter(StorageEnvironmentOptions options, string filename, long journalSize) { _options = options; _filename = filename; _handle = Win32NativeFileMethods.CreateFile(filename, Win32NativeFileAccess.GenericWrite, Win32NativeFileShare.Read, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, Win32NativeFileAttributes.Write_Through | Win32NativeFileAttributes.NoBuffering | Win32NativeFileAttributes.Overlapped, IntPtr.Zero); _pageSizeMultiplier = options.PageSize / PhysicalPageSize; if (_handle.IsInvalid) { throw new Win32Exception(); } Win32NativeFileMethods.SetFileLength(_handle, journalSize); NumberOfAllocatedPages = (int)(journalSize / _options.PageSize); _nativeOverlapped = (NativeOverlapped *)Marshal.AllocHGlobal(sizeof(NativeOverlapped)); _nativeOverlapped->InternalLow = IntPtr.Zero; _nativeOverlapped->InternalHigh = IntPtr.Zero; }
public Win32MemoryMapPager(int pageSize, string file, long?initialFileSize = null, Win32NativeFileAttributes options = Win32NativeFileAttributes.Normal, Win32NativeFileAccess access = Win32NativeFileAccess.GenericRead | Win32NativeFileAccess.GenericWrite) : base(pageSize) { Win32NativeMethods.SYSTEM_INFO systemInfo; Win32NativeMethods.GetSystemInfo(out systemInfo); AllocationGranularity = systemInfo.allocationGranularity; _access = access; _memoryMappedFileAccess = _access == Win32NativeFileAccess.GenericRead ? MemoryMappedFileAccess.Read : MemoryMappedFileAccess.ReadWrite; _handle = Win32NativeFileMethods.CreateFile(file, access, Win32NativeFileShare.Read | Win32NativeFileShare.Write | Win32NativeFileShare.Delete, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, options, IntPtr.Zero); if (_handle.IsInvalid) { int lastWin32ErrorCode = Marshal.GetLastWin32Error(); throw new IOException("Failed to open file storage of Win32MemoryMapPager for " + file, new Win32Exception(lastWin32ErrorCode)); } _fileInfo = new FileInfo(file); var streamAccessType = _access == Win32NativeFileAccess.GenericRead ? FileAccess.Read : FileAccess.ReadWrite; _fileStream = new FileStream(_handle, streamAccessType); _totalAllocationSize = _fileInfo.Length; if (_access.HasFlag(Win32NativeFileAccess.GenericWrite) || _access.HasFlag(Win32NativeFileAccess.GenericAll) || _access.HasFlag(Win32NativeFileAccess.FILE_GENERIC_WRITE)) { var fileLength = _fileStream.Length; if (fileLength == 0 && initialFileSize.HasValue) { fileLength = initialFileSize.Value; } if (_fileStream.Length == 0 || (fileLength % AllocationGranularity != 0)) { fileLength = NearestSizeToAllocationGranularity(fileLength); Win32NativeFileMethods.SetFileLength(_handle, fileLength); } _totalAllocationSize = fileLength; } NumberOfAllocatedPages = _totalAllocationSize / _pageSize; PagerState.Release(); PagerState = CreatePagerState(); }
protected internal override PagerState AllocateMorePages(long newLength) { if (DisposeOnceRunner.Disposed) { ThrowAlreadyDisposedException(); } var newLengthAfterAdjustment = NearestSizeToAllocationGranularity(newLength); if (newLengthAfterAdjustment <= _totalAllocationSize) { return(null); } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; Win32NativeFileMethods.SetFileLength(_handle, _totalAllocationSize + allocationSize); PagerState newPagerState = CreatePagerState(); newPagerState.CopyPrefetchState(this._pagerState); SetPagerState(newPagerState); PagerState.DebugVerify(newLengthAfterAdjustment); _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / Constants.Storage.PageSize; return(newPagerState); }
public static unsafe bool TryReadFileHeader(FileHeader *header, VoronPathSetting path) { using (var fs = SafeFileStream.Create(path.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.None)) { if (fs.Length != sizeof(FileHeader)) { return(false); // wrong file size } var ptr = (byte *)header; int remaining = sizeof(FileHeader); while (remaining > 0) { int read; if (Win32NativeFileMethods.ReadFile(fs.SafeFileHandle, ptr, remaining, out read, null) == false) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to read file " + path); } if (read == 0) { return(false); // we should be reading _something_ here, if we can't, then it is an error and we assume corruption } ptr += read; remaining -= read; } return(true); } }
public static unsafe bool TryReadFileHeader(FileHeader *header, string path) { using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (fs.Length != sizeof(FileHeader)) { return(false); // wrong file size } var ptr = (byte *)header; int remaining = sizeof(FileHeader); while (remaining > 0) { int read; if (Win32NativeFileMethods.ReadFile(fs.SafeFileHandle, ptr, remaining, out read, null) == false) { throw new Win32Exception(); } if (read == 0) { return(false); // we should be reading _something_ here, if we can't, then it is an error and we assume corruption } ptr += read; remaining -= read; } return(true); } }
private void WriteFile(long position, byte *p, int numberOf4Kb) { position *= 4 * Constants.Size.Kilobyte; _nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); _nativeOverlapped->OffsetHigh = (int)(position >> 32); _nativeOverlapped->EventHandle = IntPtr.Zero; Debug.Assert(_options.IoMetrics != null); bool writeSuccess; var nNumberOfBytesToWrite = numberOf4Kb * (4 * Constants.Size.Kilobyte); using (var metrics = _options.IoMetrics.MeterIoRate(_filename.FullPath, IoMetrics.MeterType.JournalWrite, nNumberOfBytesToWrite)) { int written; writeSuccess = Win32NativeFileMethods.WriteFile(_handle, p, nNumberOfBytesToWrite, out written, _nativeOverlapped); metrics.SetFileSize(NumberOfAllocated4Kb * (4 * Constants.Size.Kilobyte)); } if (writeSuccess == false) { throw new IOException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } }
protected override PagerState AllocateMorePages(long newLength) { if (Disposed) { ThrowAlreadyDisposedException(); } var newLengthAfterAdjustment = NearestSizeToAllocationGranularity(newLength); if (newLengthAfterAdjustment <= _totalAllocationSize) { return(null); } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; Win32NativeFileMethods.SetFileLength(_handle, _totalAllocationSize + allocationSize); PagerState newPagerState = null; if (TryAllocateMoreContinuousPages(allocationSize) == false) { newPagerState = CreatePagerState(); var tmp = PagerState; PagerState = newPagerState; tmp.Release(); //replacing the pager state --> so one less reference for it PagerState.DebugVerify(newLengthAfterAdjustment); } _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / _pageSize; return(newPagerState); }
public void Truncate(long size) { if (Win32NativeFileMethods.FlushFileBuffers(_handle) == false) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to sync for " + _filename); } Win32NativeFileMethods.SetFileLength(_handle, size); }
public Win32FileJournalWriter(StorageEnvironmentOptions options, VoronPathSetting filename, long journalSize, Win32NativeFileAccess access = Win32NativeFileAccess.GenericWrite, Win32NativeFileShare shareMode = Win32NativeFileShare.Read) { try { _options = options; _filename = filename; _handle = Win32NativeFileMethods.CreateFile(filename.FullPath, access, shareMode, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, options.WinOpenFlags, IntPtr.Zero); if (_handle.IsInvalid) { throw new IOException("When opening file " + filename, new Win32Exception(Marshal.GetLastWin32Error())); } var length = new FileInfo(filename.FullPath).Length; if (length < journalSize) { try { Win32NativeFileMethods.SetFileLength(_handle, journalSize); } catch (Exception) { try { _handle?.Dispose(); _handle = null; File.Delete(_filename.FullPath); } catch (Exception) { // there's nothing we can do about it } throw; } length = journalSize; } NumberOfAllocated4Kb = (int)(length / (4 * Constants.Size.Kilobyte)); _nativeOverlapped = (NativeOverlapped *)NativeMemory.AllocateMemory(sizeof(NativeOverlapped)); _nativeOverlapped->InternalLow = IntPtr.Zero; _nativeOverlapped->InternalHigh = IntPtr.Zero; } catch { Dispose(); throw; } }
public void WriteGather(long position, IntPtr[] pages) { if (Disposed) { throw new ObjectDisposedException("Win32JournalWriter"); } EnsureSegmentsSize(pages); _nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); _nativeOverlapped->OffsetHigh = (int)(position >> 32); _nativeOverlapped->EventHandle = IntPtr.Zero; // _manualResetEvent.SafeWaitHandle.DangerousGetHandle(); for (int i = 0; i < pages.Length; i++) { if (IntPtr.Size == 4) { _segments[i].Alignment = (ulong)pages[i]; } else { _segments[i].Buffer = pages[i]; } } _segments[pages.Length].Alignment = 0; // null terminating var operationCompleted = Win32NativeFileMethods.WriteFileGather(_handle, _segments, (uint)pages.Length * 4096, IntPtr.Zero, _nativeOverlapped); uint lpNumberOfBytesWritten; if (operationCompleted) { if (Win32NativeFileMethods.GetOverlappedResult(_handle, _nativeOverlapped, out lpNumberOfBytesWritten, true) == false) { throw new VoronUnrecoverableErrorException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } return; } switch (Marshal.GetLastWin32Error()) { case Win32NativeFileMethods.ErrorSuccess: case Win32NativeFileMethods.ErrorIOPending: if (Win32NativeFileMethods.GetOverlappedResult(_handle, _nativeOverlapped, out lpNumberOfBytesWritten, true) == false) { throw new VoronUnrecoverableErrorException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } break; default: throw new VoronUnrecoverableErrorException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } }
public bool Read(byte *buffer, long numOfBytes, long offsetInFile) { if (_readHandle == null) { var handle = Win32NativeFileMethods.CreateFile(_filename.FullPath, Win32NativeFileAccess.GenericRead, Win32NativeFileShare.Write | Win32NativeFileShare.Read | Win32NativeFileShare.Delete, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenExisting, Win32NativeFileAttributes.Normal, IntPtr.Zero); if (handle.IsInvalid) { throw new IOException("When opening file " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } _readHandle = handle; } var nativeOverlapped = (NativeOverlapped *)NativeMemory.AllocateMemory(sizeof(NativeOverlapped)); try { nativeOverlapped->OffsetLow = (int)(offsetInFile & 0xffffffff); nativeOverlapped->OffsetHigh = (int)(offsetInFile >> 32); nativeOverlapped->EventHandle = IntPtr.Zero; while (numOfBytes > 0) { if (Win32NativeFileMethods.ReadFile(_readHandle, buffer, (int)Math.Min(numOfBytes, int.MaxValue), out int read, nativeOverlapped) == false) { int lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == Win32NativeFileMethods.ErrorHandleEof) { return(false); } if (lastWin32Error == Win32NativeFileMethods.ErrorInvalidHandle) { _readHandle = null; } throw new Win32Exception(lastWin32Error, $"Unable to read from {_filename}, error code: {lastWin32Error}"); } numOfBytes -= read; buffer += read; offsetInFile += read; nativeOverlapped->OffsetLow = (int)(offsetInFile & 0xffffffff); nativeOverlapped->OffsetHigh = (int)(offsetInFile >> 32); } return(true); } finally { NativeMemory.Free((byte *)nativeOverlapped, sizeof(NativeOverlapped)); } }
public void WriteGather(long position, IntPtr[] pages) { if (Disposed) { throw new ObjectDisposedException("Win32JournalWriter"); } var physicalPages = EnsureSegmentsSize(pages); _nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); _nativeOverlapped->OffsetHigh = (int)(position >> 32); _nativeOverlapped->EventHandle = IntPtr.Zero; PreparePagesToWrite(pages); var sp = Stopwatch.StartNew(); // WriteFileGather will only be able to write x pages of size GetSystemInfo().dwPageSize. Usually that is 4096 (4kb). If you are // having trouble with this method, ensure that this value havent changed for your environment. var operationCompleted = Win32NativeFileMethods.WriteFileGather(_handle, _segments, (uint)(physicalPages * PhysicalPageSize), IntPtr.Zero, _nativeOverlapped); uint lpNumberOfBytesWritten; var sizeToWrite = physicalPages * PhysicalPageSize; if (operationCompleted) { if (Win32NativeFileMethods.GetOverlappedResult(_handle, _nativeOverlapped, out lpNumberOfBytesWritten, true) == false) { throw new VoronUnrecoverableErrorException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } // TODO : Measure IO times (RavenDB-4659) - Wrote {sizeToWrite/1024:#,#} kb in {sp.ElapsedMilliseconds:#,#} ms return; } switch (Marshal.GetLastWin32Error()) { case Win32NativeFileMethods.ErrorSuccess: case Win32NativeFileMethods.ErrorIOPending: if (Win32NativeFileMethods.GetOverlappedResult(_handle, _nativeOverlapped, out lpNumberOfBytesWritten, true) == false) { throw new VoronUnrecoverableErrorException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } // TODO : Measure IO times (RavenDB-4659) - Wrote {sizeToWrite/1024:#,#} kb in {sp.ElapsedMilliseconds:#,#} ms break; default: throw new VoronUnrecoverableErrorException("Could not write to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } }
public override void AllocateMorePages(Transaction tx, long newLength) { ThrowObjectDisposedIfNeeded(); var newLengthAfterAdjustment = NearestSizeToAllocationGranularity(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; 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 bool Read(long pageNumber, byte *buffer, int count) { if (_readHandle == null) { _readHandle = Win32NativeFileMethods.CreateFile(_filename, Win32NativeFileAccess.GenericRead, Win32NativeFileShare.Write | Win32NativeFileShare.Read | Win32NativeFileShare.Delete, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenExisting, Win32NativeFileAttributes.Normal, IntPtr.Zero); } long position = pageNumber * _options.PageSize; NativeOverlapped *nativeOverlapped = (NativeOverlapped *)Marshal.AllocHGlobal(sizeof(NativeOverlapped)); try { nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); nativeOverlapped->OffsetHigh = (int)(position >> 32); nativeOverlapped->EventHandle = IntPtr.Zero; while (count > 0) { int read; if (Win32NativeFileMethods.ReadFile(_readHandle, buffer, count, out read, nativeOverlapped) == false) { int lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == Win32NativeFileMethods.ErrorHandleEof) { return(false); } throw new Win32Exception(lastWin32Error); } count -= read; buffer += read; position += read; nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); nativeOverlapped->OffsetHigh = (int)(position >> 32); } return(true); } finally { Marshal.FreeHGlobal((IntPtr)nativeOverlapped); } }
public bool Read(long pageNumber, byte *buffer, int count) { if (_readHandle == null) { _readHandle = Win32NativeFileMethods.CreateFile(_filename, Win32NativeFileAccess.GenericRead, Win32NativeFileShare.Write | Win32NativeFileShare.Read | Win32NativeFileShare.Delete, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenExisting, Win32NativeFileAttributes.Normal, IntPtr.Zero); } long position = pageNumber * AbstractPager.PageSize; var overlapped = new Overlapped((int)(position & 0xffffffff), (int)(position >> 32), IntPtr.Zero, null); NativeOverlapped *nativeOverlapped = overlapped.Pack(null, null); try { while (count > 0) { int read; if (Win32NativeFileMethods.ReadFile(_readHandle, buffer, count, out read, nativeOverlapped) == false) { int lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error == Win32NativeFileMethods.ErrorHandleEof) { return(false); } throw new Win32Exception(lastWin32Error); } count -= read; buffer += read; position += read; nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); nativeOverlapped->OffsetHigh = (int)(position >> 32); } return(true); } finally { Overlapped.Free(nativeOverlapped); } }
public void WriteBuffer(long position, byte *srcPointer, int sizeToWrite) { if (Disposed) { throw new ObjectDisposedException("Win32JournalWriter"); } int written; _nativeOverlapped->OffsetLow = (int)(position & 0xffffffff); _nativeOverlapped->OffsetHigh = (int)(position >> 32); _nativeOverlapped->EventHandle = IntPtr.Zero; var sp = Stopwatch.StartNew(); var operationCompleted = Win32NativeFileMethods.WriteFile(_handle, srcPointer, sizeToWrite, out written, _nativeOverlapped); uint lpNumberOfBytesWritten; if (operationCompleted) { if (Win32NativeFileMethods.GetOverlappedResult(_handle, _nativeOverlapped, out lpNumberOfBytesWritten, true) == false) { throw new VoronUnrecoverableErrorException("Could not write lazy buffer to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } // TODO : Measure IO times (RavenDB-4659) - Wrote {sizeToWrite/1024:#,#} kb in {sp.ElapsedMilliseconds:#,#} ms return; } switch (Marshal.GetLastWin32Error()) { case Win32NativeFileMethods.ErrorSuccess: case Win32NativeFileMethods.ErrorIOPending: if (Win32NativeFileMethods.GetOverlappedResult(_handle, _nativeOverlapped, out lpNumberOfBytesWritten, true) == false) { throw new VoronUnrecoverableErrorException("Could not write lazy buffer to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } // TODO : Measure IO times (RavenDB-4659) - Wrote {sizeToWrite / 1024:#,#} kb in {sp.ElapsedMilliseconds:#,#} ms break; default: throw new VoronUnrecoverableErrorException("Could not write lazy buffer to journal " + _filename, new Win32Exception(Marshal.GetLastWin32Error())); } }
protected override PagerState AllocateMorePages(long newLength) { if (Disposed) { ThrowAlreadyDisposedException(); } var newLengthAfterAdjustment = NearestSizeToAllocationGranularity(newLength); if (newLengthAfterAdjustment <= _totalAllocationSize) { return(null); } var allocationSize = newLengthAfterAdjustment - _totalAllocationSize; Win32NativeFileMethods.SetFileLength(_handle, _totalAllocationSize + allocationSize); PagerState newPagerState = null; #if VALIDATE // If we're on validate more, we don't want to allocate continuous pages because this // introduces weird conditions on the protection and unprotection routines (we have to // track boundaries, which is more complex than we're willing to do) newPagerState = CreatePagerState(); SetPagerState(newPagerState); PagerState.DebugVerify(newLengthAfterAdjustment); #else if (TryAllocateMoreContinuousPages(allocationSize) == false) { newPagerState = CreatePagerState(); SetPagerState(newPagerState); PagerState.DebugVerify(newLengthAfterAdjustment); } #endif _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / PageSize; return(newPagerState); }
public static unsafe void WriteFileHeader(FileHeader *header, string path) { using (var fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { var ptr = (byte *)header; int remaining = sizeof(FileHeader); while (remaining > 0) { int read; if (Win32NativeFileMethods.WriteFile(fs.SafeFileHandle, ptr, remaining, out read, null) == false) { throw new Win32Exception(); } ptr += read; remaining -= read; } Win32NativeFileMethods.FlushFileBuffers(fs.SafeFileHandle); } }
public Win32FileJournalWriter(string filename, long journalSize) { _filename = filename; _handle = Win32NativeFileMethods.CreateFile(filename, Win32NativeFileAccess.GenericWrite, Win32NativeFileShare.Read, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, Win32NativeFileAttributes.Write_Through | Win32NativeFileAttributes.NoBuffering | Win32NativeFileAttributes.Overlapped, IntPtr.Zero); if (_handle.IsInvalid) { throw new Win32Exception(); } try { Win32NativeFileMethods.SetFileLength(_handle, journalSize); } catch (Exception ex) { try { _handle?.Dispose(); _handle = null; File.Delete(_filename); } catch (Exception) { // there's nothing we can do about it } throw new IOException("When SetFileLength file " + filename + " to " + journalSize, ex); } NumberOfAllocatedPages = journalSize / AbstractPager.PageSize; _nativeOverlapped = (NativeOverlapped *)Marshal.AllocHGlobal(sizeof(NativeOverlapped)); _nativeOverlapped->InternalLow = IntPtr.Zero; _nativeOverlapped->InternalHigh = IntPtr.Zero; }
public static unsafe void WriteFileHeader(FileHeader *header, VoronPathSetting path) { using (var fs = SafeFileStream.Create(path.FullPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.None)) { var ptr = (byte *)header; int remaining = sizeof(FileHeader); while (remaining > 0) { int written; if (Win32NativeFileMethods.WriteFile(fs.SafeFileHandle, ptr, remaining, out written, null) == false) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to write to file " + path); } ptr += written; remaining -= written; } if (Win32NativeFileMethods.FlushFileBuffers(fs.SafeFileHandle) == false) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to Flush File Buffers (sync) of file " + path); } } }
public Win32FileJournalWriter(string filename, long journalSize) { _filename = filename; _handle = Win32NativeFileMethods.CreateFile(filename, Win32NativeFileAccess.GenericWrite, Win32NativeFileShare.Read, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, Win32NativeFileAttributes.Write_Through | Win32NativeFileAttributes.NoBuffering | Win32NativeFileAttributes.Overlapped, IntPtr.Zero); if (_handle.IsInvalid) { throw new Win32Exception(); } Win32NativeFileMethods.SetFileLength(_handle, journalSize); NumberOfAllocatedPages = journalSize / AbstractPager.PageSize; _nativeOverlapped = (NativeOverlapped *)Marshal.AllocHGlobal(sizeof(NativeOverlapped)); _nativeOverlapped->InternalLow = IntPtr.Zero; _nativeOverlapped->InternalHigh = IntPtr.Zero; }
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) { RefreshMappedView(tx); PagerState.DebugVerify(newLengthAfterAdjustment); } _totalAllocationSize += allocationSize; NumberOfAllocatedPages = _totalAllocationSize / PageSize; }
private void WriteFile(long position, byte *p, int numberOf4Kb) { Debug.Assert(_options.IoMetrics != null); SetOverlappedPosition(position); bool writeSuccess; var nNumberOfBytesToWrite = numberOf4Kb * (4 * Constants.Size.Kilobyte); using (var metrics = _options.IoMetrics.MeterIoRate(_filename.FullPath, IoMetrics.MeterType.JournalWrite, nNumberOfBytesToWrite)) { int written; writeSuccess = Win32NativeFileMethods.WriteFile(_handle, p, nNumberOfBytesToWrite, out written, _nativeOverlapped); if (writeSuccess == false) { HandleWriteError(position, p, numberOf4Kb); } metrics.SetFileSize(NumberOfAllocated4Kb * (4 * Constants.Size.Kilobyte)); } }
private void HandleWriteError(long position, byte *p, int numberOf4Kb) { var errorCode = Marshal.GetLastWin32Error(); if (errorCode != ERROR_WORKING_SET_QUOTA) { ThrowOnWriteFileFailure(errorCode); } // this error can happen under low memory conditions, instead of trying to write the whole thing in a single shot // we'll write it in 4KB increments. This is likely to be much slower, but failing here will fail the entire DB for (int i = 0; i < numberOf4Kb; i++) { SetOverlappedPosition(position + i); var writeSuccess = Win32NativeFileMethods.WriteFile(_handle, p + (i * (4 * Constants.Size.Kilobyte)), (4 * Constants.Size.Kilobyte), out var written, _nativeOverlapped); if (writeSuccess == false) { ThrowOnWriteFileFailure(Marshal.GetLastWin32Error()); } } }
public WindowsMemoryMapPager(StorageEnvironmentOptions options, VoronPathSetting file, long?initialFileSize = null, Win32NativeFileAttributes fileAttributes = Win32NativeFileAttributes.Normal, Win32NativeFileAccess access = Win32NativeFileAccess.GenericRead | Win32NativeFileAccess.GenericWrite, bool usePageProtection = false) : base(options, !fileAttributes.HasFlag(Win32NativeFileAttributes.Temporary), usePageProtection) { SYSTEM_INFO systemInfo; GetSystemInfo(out systemInfo); FileName = file; _logger = LoggingSource.Instance.GetLogger <StorageEnvironment>($"Pager-{file}"); _access = access; _copyOnWriteMode = Options.CopyOnWriteMode && FileName.FullPath.EndsWith(Constants.DatabaseFilename); if (_copyOnWriteMode) { _memoryMappedFileAccess = MemoryMappedFileAccess.Read | MemoryMappedFileAccess.CopyOnWrite; fileAttributes = Win32NativeFileAttributes.Readonly; _access = Win32NativeFileAccess.GenericRead; } else { _memoryMappedFileAccess = _access == Win32NativeFileAccess.GenericRead ? MemoryMappedFileAccess.Read : MemoryMappedFileAccess.ReadWrite; } _fileAttributes = fileAttributes; _handle = Win32NativeFileMethods.CreateFile(file.FullPath, access, Win32NativeFileShare.Read | Win32NativeFileShare.Write | Win32NativeFileShare.Delete, IntPtr.Zero, Win32NativeFileCreationDisposition.OpenAlways, fileAttributes, IntPtr.Zero); if (_handle.IsInvalid) { int lastWin32ErrorCode = Marshal.GetLastWin32Error(); throw new IOException("Failed to open file storage of WinMemoryMapPager for " + file, new Win32Exception(lastWin32ErrorCode)); } _fileInfo = new FileInfo(file.FullPath); var drive = _fileInfo.Directory.Root.Name.TrimEnd('\\'); try { if (PhysicalDrivePerMountCache.TryGetValue(drive, out UniquePhysicalDriveId) == false) { UniquePhysicalDriveId = GetPhysicalDriveId(drive); } if (_logger.IsInfoEnabled) { _logger.Info($"Physical drive '{drive}' unique id = '{UniquePhysicalDriveId}' for file '{file}'"); } } catch (Exception ex) { UniquePhysicalDriveId = 0; if (_logger.IsInfoEnabled) { _logger.Info($"Failed to determine physical drive Id for drive letter '{drive}', file='{file}'", ex); } } var streamAccessType = _access == Win32NativeFileAccess.GenericRead ? FileAccess.Read : FileAccess.ReadWrite; _fileStream = SafeFileStream.Create(_handle, streamAccessType); _totalAllocationSize = _fileInfo.Length; if ((access & Win32NativeFileAccess.GenericWrite) == Win32NativeFileAccess.GenericWrite || (access & Win32NativeFileAccess.GenericAll) == Win32NativeFileAccess.GenericAll || (access & Win32NativeFileAccess.FILE_GENERIC_WRITE) == Win32NativeFileAccess.FILE_GENERIC_WRITE) { var fileLength = _fileStream.Length; if (fileLength == 0 && initialFileSize.HasValue) { fileLength = initialFileSize.Value; } if (_fileStream.Length == 0 || (fileLength % AllocationGranularity != 0)) { fileLength = NearestSizeToAllocationGranularity(fileLength); Win32NativeFileMethods.SetFileLength(_handle, fileLength); } _totalAllocationSize = fileLength; } NumberOfAllocatedPages = _totalAllocationSize / Constants.Storage.PageSize; SetPagerState(CreatePagerState()); }