internal static SafeMapViewHandle MapViewOfFile( SafeMapHandle hMap, long fileOffset, long mapViewSize, FileMapAccess desiredAccess) { if (hMap == null || hMap.IsInvalid) { throw new ArgumentNullException("hMap"); } if (fileOffset < 0) { throw new ArgumentOutOfRangeException("fileOffset", fileOffset, "Must be >= 0"); } if (mapViewSize <= 0) { throw new ArgumentOutOfRangeException("mapViewSize", mapViewSize, "Must be > 0"); } return (ThrowOnError( MapViewOfFile( hMap, desiredAccess, (uint)((fileOffset >> 32) & 0xFFFFFFFF), (uint)(fileOffset & 0xFFFFFFFF), (IntPtr)mapViewSize))); }
private static extern SafeMapViewHandle MapViewOfFile( SafeMapHandle hFileMappingObject, FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, IntPtr dwNumberOfBytesToMap);
private int ProcessMemoryMappedFile(long firstItemIdx, ArraySegment <T> buffer, bool isWriting, long fileSize) { SafeMapHandle hMap = null; try { bool isAligned; long fileCount = CalculateItemCountFromFilePosition(fileSize, out isAligned); if (!isAligned && isWriting) { throw new BinaryFileException( "Cannot write to a file when its length does not align to item size ({0})", ToString()); } long idxToStopAt = firstItemIdx + buffer.Count; if (!isWriting && idxToStopAt > fileCount) { idxToStopAt = fileCount; } long offsetToStopAt = ItemIdxToOffset(idxToStopAt); long idxCurrent = firstItemIdx; // Grow file if needed if (isWriting && offsetToStopAt > fileSize) { fileSize = offsetToStopAt; } hMap = NativeWinApis.CreateFileMapping( (FileStream)BaseStream, fileSize, isWriting ? FileMapProtection.PageReadWrite : FileMapProtection.PageReadOnly); while (idxCurrent < idxToStopAt) { SafeMapViewHandle ptrMapViewBaseAddr = null; try { long offsetCurrent = ItemIdxToOffset(idxCurrent); long mapViewFileOffset = Utils.RoundDownToMultiple(offsetCurrent, MinPageSize); long mapViewSize = offsetToStopAt - mapViewFileOffset; long itemsToProcessThisRun = idxToStopAt - idxCurrent; if (mapViewSize > MaxLargePageSize) { mapViewSize = MaxLargePageSize; itemsToProcessThisRun = (mapViewFileOffset + mapViewSize) / ItemSize - idxCurrent - CalculateHeaderSizeAsItemCount(); } // The size of the new map view. ptrMapViewBaseAddr = NativeWinApis.MapViewOfFile( hMap, mapViewFileOffset, mapViewSize, isWriting ? FileMapAccess.Write : FileMapAccess.Read); long totalItemsDone = idxCurrent - firstItemIdx; long bufItemOffset = buffer.Offset + totalItemsDone; // Access file using memory-mapped pages Serializer.ProcessMemoryPtr( (IntPtr)(ptrMapViewBaseAddr.Address + offsetCurrent - mapViewFileOffset), new ArraySegment <T>(buffer.Array, (int)bufItemOffset, (int)itemsToProcessThisRun), isWriting); idxCurrent += itemsToProcessThisRun; } finally { if (ptrMapViewBaseAddr != null) { ptrMapViewBaseAddr.Dispose(); } } } return((int)(idxCurrent - firstItemIdx)); } finally { if (hMap != null) { hMap.Dispose(); } } }