Beispiel #1
0
        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);
        }
Beispiel #2
0
 protected override bool ReleaseHandle()
 {
     return(NativeWinApis.UnmapViewOfFile(handle));
 }
Beispiel #3
0
 protected override bool ReleaseHandle()
 {
     return(NativeWinApis.CloseHandle(handle));
 }
Beispiel #4
0
        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();
                }
            }
        }