Пример #1
0
        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 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;
        }
        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);
        }
Пример #5
0
        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;
        }
Пример #6
0
 public void Truncate(long size)
 {
     if (Win32NativeFileMethods.FlushFileBuffers(_handle) == false)
     {
         throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to sync for " + _filename);
     }
     Win32NativeFileMethods.SetFileLength(_handle, size);
 }
Пример #7
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;
            }
        }
Пример #8
0
        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;
        }
Пример #9
0
        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);
        }
Пример #10
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();
            }

            Win32NativeFileMethods.SetFileLength(_handle, journalSize);

            NumberOfAllocatedPages = journalSize / AbstractPager.PageSize;

            _nativeOverlapped = (NativeOverlapped *)Marshal.AllocHGlobal(sizeof(NativeOverlapped));

            _nativeOverlapped->InternalLow  = IntPtr.Zero;
            _nativeOverlapped->InternalHigh = IntPtr.Zero;
        }
Пример #11
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;
        }
Пример #12
0
        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;
        }
Пример #13
0
        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());
        }