private unsafe int ProcessFileStreamPtr( FileStream fileStream, void *bufPtr, int offset, int count, bool isWriting) { byte *byteBufPtr = (byte *)bufPtr + offset * _typeSize; int byteCount = count * _typeSize; var bytesProcessed = (int)(isWriting ? NativeWinApis.WriteFile(fileStream, byteBufPtr, byteCount) : NativeWinApis.ReadFile(fileStream, byteBufPtr, byteCount)); if (isWriting && bytesProcessed != byteCount) { throw new SerializerException( "Unable to write {0} bytes - only {1} bytes were done", byteCount, bytesProcessed); } if (!isWriting && bytesProcessed % _typeSize != 0) { throw new SerializerException( "Incomplete items were detected while reading: {0} items ({1} bytes) requested, {2} bytes read", count, byteCount, bytesProcessed); } return(bytesProcessed / _typeSize); }
protected override bool ReleaseHandle() { return(NativeWinApis.UnmapViewOfFile(handle)); }
protected override bool ReleaseHandle() { return(NativeWinApis.CloseHandle(handle)); }
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(); } } }