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();
        }
        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 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;
        }
Exemple #4
0
        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;
            }
        }
Exemple #5
0
        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 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 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;
        }
Exemple #9
0
        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 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());
        }