private SafeFileHandle CreateHandle(int segmentId) { uint fileAccess = Native32.GENERIC_READ | Native32.GENERIC_WRITE; uint fileShare = unchecked (((uint)FileShare.ReadWrite & ~(uint)FileShare.Inheritable)); uint fileCreation = unchecked ((uint)FileMode.OpenOrCreate); uint fileFlags = Native32.FILE_FLAG_OVERLAPPED; fileFlags = fileFlags | Native32.FILE_FLAG_NO_BUFFERING; if (deleteOnClose) { fileFlags = fileFlags | Native32.FILE_FLAG_DELETE_ON_CLOSE; // FILE_SHARE_DELETE allows multiple FASTER instances to share a single log directory and each can specify deleteOnClose. // This will allow the files to persist until all handles across all instances have been closed. fileShare = fileShare | Native32.FILE_SHARE_DELETE; } var logHandle = Native32.CreateFileW( GetSegmentName(segmentId), fileAccess, fileShare, IntPtr.Zero, fileCreation, fileFlags, IntPtr.Zero); if (logHandle.IsInvalid) { var error = Marshal.GetLastWin32Error(); throw new IOException($"Error creating log file for {GetSegmentName(segmentId)}, error: {error}", Native32.MakeHRFromErrorCode(error)); } if (preallocateFile) { SetFileSize(FileName, logHandle, segmentSize); } try { ThreadPool.BindHandle(logHandle); } catch (Exception e) { throw new Exception("Error binding log handle for " + GetSegmentName(segmentId) + ": " + e.ToString()); } return(logHandle); }
/// <summary> /// Creates a SafeFileHandle for the specified segment. This can be used by derived classes to prepopulate logHandles in the constructor. /// </summary> protected internal static SafeFileHandle CreateHandle(int segmentId, bool disableFileBuffering, bool deleteOnClose, bool preallocateFile, long segmentSize, string fileName, IntPtr ioCompletionPort) { uint fileAccess = Native32.GENERIC_READ | Native32.GENERIC_WRITE; uint fileShare = unchecked (((uint)FileShare.ReadWrite & ~(uint)FileShare.Inheritable)); uint fileCreation = unchecked ((uint)FileMode.OpenOrCreate); uint fileFlags = Native32.FILE_FLAG_OVERLAPPED; if (disableFileBuffering) { fileFlags = fileFlags | Native32.FILE_FLAG_NO_BUFFERING; } if (deleteOnClose) { fileFlags = fileFlags | Native32.FILE_FLAG_DELETE_ON_CLOSE; // FILE_SHARE_DELETE allows multiple FASTER instances to share a single log directory and each can specify deleteOnClose. // This will allow the files to persist until all handles across all instances have been closed. fileShare = fileShare | Native32.FILE_SHARE_DELETE; } var logHandle = Native32.CreateFileW( GetSegmentName(fileName, segmentId), fileAccess, fileShare, IntPtr.Zero, fileCreation, fileFlags, IntPtr.Zero); if (logHandle.IsInvalid) { var error = Marshal.GetLastWin32Error(); throw new IOException($"Error creating log file for {GetSegmentName(fileName, segmentId)}, error: {error}", Native32.MakeHRFromErrorCode(error)); } if (preallocateFile && segmentSize != -1) { SetFileSize(fileName, logHandle, segmentSize); } if (ioCompletionPort != IntPtr.Zero) { ThreadPool.GetMaxThreads(out int workerThreads, out _); Native32.CreateIoCompletionPort(logHandle, ioCompletionPort, (UIntPtr)(long)logHandle.DangerousGetHandle(), (uint)(workerThreads + NumCompletionThreads)); } else { try { ThreadPool.BindHandle(logHandle); } catch (Exception e) { throw new FasterException("Error binding log handle for " + GetSegmentName(fileName, segmentId) + ": " + e.ToString()); } } return(logHandle); }