Exemple #1
0
 public void Close()
 {
     //if (PE.IsAttached)
     //{
     //    PE.Dettach();
     //    OnEventNotify(Closed);
     //}
     if (smmv != null)
     {
         smmv.ReleasePointer();
         smmv = null;
     }
     if (mmva != null)
     {
         // mmva.Dispose(); 会自己析构不用管,下同
         mmva = null;
     }
     if (mmf != null)
     {
         mmf = null;
     }
     if (fs != null)
     {
         fs.Close();
         fs = null;
     }
 }
Exemple #2
0
        public unsafe void CopyMemoryFromOffset(ulong rva, IntPtr destination, uint size)
        {
            try
            {
                byte *baseOfView = null;

                _mappedFileView.AcquirePointer(ref baseOfView);

                IntPtr readAddress = new IntPtr(baseOfView + rva);

                windows.RtlMoveMemory(destination, readAddress, new IntPtr(size));
            }
            finally
            {
                _mappedFileView.ReleasePointer();
            }
        }
Exemple #3
0
        public void Flush(IntPtr capacity)
        {
            if (m_viewHandle != null)
            {
                unsafe {
                    byte *firstPagePtr = null;
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try {
                        m_viewHandle.AcquirePointer(ref firstPagePtr);

                        bool success = UnsafeNativeMethods.FlushViewOfFile(firstPagePtr, capacity);
                        if (success)
                        {
                            return; // This will visit the finally block.
                        }
                        // It is a known issue within the NTFS transaction log system that
                        // causes FlushViewOfFile to intermittently fail with ERROR_LOCK_VIOLATION
                        // [http://bugcheck/bugs/Windows8Bugs/152862].
                        // As a workaround, we catch this particular error and retry the flush operation
                        // a few milliseconds later. If it does not work, we give it a few more tries with
                        // increasing intervals. Eventually, however, we need to give up. In ad-hoc tests
                        // this strategy successfully flushed the view after no more than 3 retries.

                        Int32 error    = Marshal.GetLastWin32Error();
                        bool  canRetry = (!success && error == UnsafeNativeMethods.ERROR_LOCK_VIOLATION);

                        for (Int32 w = 0; canRetry && w < MaxFlushWaits; w++)
                        {
                            Int32 pause = (1 << w);  // MaxFlushRetries should never be over 30
                            Thread.Sleep(pause);

                            for (Int32 r = 0; canRetry && r < MaxFlushRetriesPerWait; r++)
                            {
                                success = UnsafeNativeMethods.FlushViewOfFile(firstPagePtr, capacity);
                                if (success)
                                {
                                    return; // This will visit the finally block.
                                }
                                Thread.Sleep(0);

                                error    = Marshal.GetLastWin32Error();
                                canRetry = (error == UnsafeNativeMethods.ERROR_LOCK_VIOLATION);
                            }
                        }

                        // We got too here, so there was no success:
                        __Error.WinIOError(error, String.Empty);
                    }
                    finally {
                        if (firstPagePtr != null)
                        {
                            m_viewHandle.ReleasePointer();
                        }
                    }
                }
            }
        }
Exemple #4
0
            protected override bool ReleaseHandle()
            {
                // The operating system will release these handles when the process terminates, so do not spend time
                // releasing them manually in that case. Doing so causes unnecessary delays during application shutdown.
                if (!Environment.HasShutdownStarted)
                {
                    _viewHandle.ReleasePointer();
                }

                return(true);
            }
        private Win32MemoryMappedFile(FileStream fs, SafeMemoryMappedFileHandle handle, ulong size)
        {
            Contract.Requires(fs != null && handle != null && !handle.IsInvalid && !handle.IsClosed);
            m_mapHandle = handle;
            m_file      = fs;
            m_size      = size;

            // verify that it fits on 32 bit OS...
            if (IntPtr.Size == 4 && size > uint.MaxValue)
            {              // won't work with 32-bit pointers
                throw new InvalidOperationException("Memory mapped file size is too big to be opened on a 32-bit system.");
            }

            // verifiy that it will fit in the virtual address space of the process
            var totalVirtual = UnsafeNativeMethods.GetTotalVirtualAddressSpaceSize();

            if (size > totalVirtual)
            {
                throw new InvalidOperationException("Memory mapped file size is too big to fit in the current process virtual address space");
            }

            SafeMemoryMappedViewHandle view = null;
            byte *baseAddress = null;

            try
            {
                view = UnsafeNativeMethods.MapViewOfFile(m_mapHandle, UnsafeNativeMethods.FileMapAccess.FileMapRead, 0, 0, new UIntPtr(size));
                if (view.IsInvalid)
                {
                    throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
                }
                view.Initialize(size);
                m_viewHandle = view;

                view.AcquirePointer(ref baseAddress);
                m_baseAddress = baseAddress;
            }
            catch
            {
                if (baseAddress != null)
                {
                    view.ReleasePointer();
                }
                if (view != null)
                {
                    view.Dispose();
                }
                m_file        = null;
                m_viewHandle  = null;
                m_mapHandle   = null;
                m_baseAddress = null;
                throw;
            }
        }
Exemple #6
0
        public unsafe int Read(byte[] buffer, int offset, int count)
        {
            long position = _position + _origin;

            long numOfBytesToRead = _length - position;

            if (numOfBytesToRead > count)
            {
                numOfBytesToRead = count;
            }

            if (numOfBytesToRead <= 0)
            {
                return(0);
            }

            byte *pointer = null;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                _buffer.AcquirePointer(ref pointer);
                BufferUtils.Memcpy((byte *)(pointer + position), 0, buffer, offset, count);
            }
            finally
            {
                if (pointer != null)
                {
                    _buffer.ReleasePointer();
                }
            }

            _position += count;

            return(count);
        }
        public ReadOnlySpan <byte> ReadSpan()
        {
            va  = mm.CreateViewStream();
            mma = va.SafeMemoryMappedViewHandle;

            ReadOnlySpan <byte> bytes;

            unsafe {
                byte *ptrMemMap = (byte *)0;
                mma.AcquirePointer(ref ptrMemMap);
                bytes = new ReadOnlySpan <byte>(ptrMemMap, (int)mma.ByteLength);
                mma.ReleasePointer();
            }

            return(bytes);
        }
Exemple #8
0
            public override unsafe int Read(TiffStreamOffset offset, Memory <byte> buffer)
            {
                MemoryMappedFile?file = Volatile.Read(ref _file);

                if (file is null)
                {
                    throw new ObjectDisposedException(nameof(ContentReader));
                }

                if (offset.Offset + buffer.Length > _capacity)
                {
                    buffer = buffer.Slice(0, Math.Max(0, (int)(_capacity - offset.Offset)));
                }

                if (buffer.IsEmpty)
                {
                    return(0);
                }

                using (MemoryMappedViewAccessor accessor = file.CreateViewAccessor(offset, 0, MemoryMappedFileAccess.Read))
                {
                    byte *pointer = null;
                    SafeMemoryMappedViewHandle handle = accessor.SafeMemoryMappedViewHandle;

#if !NETSTANDARD1_3
                    System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
#endif

                    try
                    {
                        handle.AcquirePointer(ref pointer);
                        if (pointer != null)
                        {
                            new Span <byte>(pointer + accessor.PointerOffset, buffer.Length).CopyTo(buffer.Span);
                        }

                        return(buffer.Length);
                    }
                    finally
                    {
                        if (pointer != null)
                        {
                            handle.ReleasePointer();
                        }
                    }
                }
            }
        public void Dispose()
        {
            if (!m_disposed)
            {
                m_disposed = true;

                if (m_viewHandle != null)
                {
                    if (m_baseAddress != null)
                    {
                        m_viewHandle.ReleasePointer();
                    }
                    m_viewHandle.Dispose();
                }
                if (m_mapHandle != null)
                {
                    m_mapHandle.Dispose();
                }
                if (m_file != null)
                {
                    m_file.Dispose();
                }
            }
        }
Exemple #10
0
        internal void Grow(long minCapacity, bool sparse = false)
        {
            if (minCapacity < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(nameof(minCapacity));
            }

            if (_isWritable)
            {
                minCapacity = ((minCapacity - 1) / 4096 + 1) * 4096;
            }

            if (_fileStream == null)
            {
                // NB No need to recreate file
                // If capacity is larger than the size of the file on disk, the file on disk is
                // increased to match the specified capacity even if no data is written to the
                // memory-mapped file. To prevent this from occurring, specify 0 (zero) for the
                // default capacity, which will internally set capacity to the size of the file on disk.

                //var handle = Mono.Posix.Syscall.open(_filePath, (Mono.Posix.OpenFlags) (0)); // _isWritable
                //    //? Mono.Posix.OpenFlags.O_RDWR //| Mono.Posix.OpenFlags.O_CREAT
                //    //: Mono.Posix.OpenFlags.O_RDONLY); //, FileMode.S_IWUSR | FileMode.S_IRUSR | FileMode.S_IROTH | FileMode.S_IWOTH);
                //var sfh = new SafeFileHandle((IntPtr)handle, true);

                //_fileStream = new FileStream(sfh, _isWritable ? FileAccess.ReadWrite : FileAccess.Read, 1, false);

                _fileStream = new FileStream(_filePath, _isWritable ? FileMode.OpenOrCreate : FileMode.Open,
                                             _isWritable ? FileAccess.ReadWrite : FileAccess.Read,
                                             FileShare.ReadWrite, 1,
                                             _fileOptions);

                if (sparse)
                {
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        if (!MarkAsSparseFile(_fileStream))
                        {
                            throw new Win32Exception("Cannot make a sparse file.");
                        }
                    }
                    else
                    {
                        // We allocate in chunks of 64-128 MB, not a big deal for servers
                        // Need this for MacOS, it's not nice to have pre-allocated 1 GB
                        // just in case.
                        Trace.TraceWarning("Sparse files not implemented on non-Windows");
                    }
                }

                if (!_isWritable && _fileStream.Length == 0)
                {
                    _fileStream.Dispose();
                    _fileStream = null;
                    ThrowHelper.ThrowInvalidOperationException($"File {_filePath} is empty. Cannot open DirectFile in read-only mode.");
                    return;
                }
            }
            else if (_isWritable)
            {
                // _va.Dispose does this
                // Flush(flushToDisk);
            }

            if (!_isWritable && minCapacity > _fileStream.Length)
            {
                ThrowHelper.ThrowArgumentException("minCapacity > _fileStream.Length");
            }

            // NB another thread could have increased the map size and _capacity could be stale
            var bytesCapacity = Math.Max(_fileStream.Length, minCapacity);

            _va?.Flush();
            _vaHandle?.ReleasePointer();
            _vaHandle?.Dispose();
            _va?.Dispose();
            _mmf?.Dispose();

            // var unique = ((long)Process.GetCurrentProcess().Id << 32) | _counter++;
            // NB: map name must be unique
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream,
                                                      null, // $@"{Path.GetFileName(_filePath)}.{unique}"
                                                      bytesCapacity,
                                                      _isWritable ? MemoryMappedFileAccess.ReadWrite : MemoryMappedFileAccess.Read, HandleInheritability.None,
                                                      true);

            _mmf = mmf;

            byte *ptr = (byte *)0;

            _va       = _mmf.CreateViewAccessor(0, bytesCapacity, _isWritable ? MemoryMappedFileAccess.ReadWrite : MemoryMappedFileAccess.Read);
            _vaHandle = _va.SafeMemoryMappedViewHandle;
            _vaHandle.AcquirePointer(ref ptr);

            _pointer  = ptr;
            _capacity = bytesCapacity;
        }