Пример #1
0
        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()));
            }
        }
Пример #2
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;
        }
        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();
        }
Пример #5
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);
        }
Пример #6
0
 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);
     }
 }
Пример #7
0
 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);
     }
 }
Пример #8
0
        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);
        }
Пример #10
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);
 }
Пример #11
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;
            }
        }
Пример #12
0
        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()));
            }
        }
Пример #13
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));
            }
        }
Пример #14
0
        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()));
            }
        }
Пример #15
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;
        }
Пример #16
0
        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);
            }
        }
Пример #17
0
        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);
            }
        }
Пример #18
0
        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()));
            }
        }
Пример #19
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);
        }
Пример #20
0
 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);
     }
 }
Пример #21
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;
        }
Пример #22
0
 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);
         }
     }
 }
Пример #23
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;
        }
Пример #24
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;
        }
Пример #25
0
        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));
            }
        }
Пример #26
0
        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());
                }
            }
        }
Пример #27
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());
        }