Example #1
0
        private CancellationToken CreateToken(ulong connectionId)
        {
            Debug.WriteLine("Server: Registering connection for disconnect for connection ID: " + connectionId);

            // Create a nativeOverlapped callback so we can register for disconnect callback
            var overlapped = new Overlapped();
            var cts        = new CancellationTokenSource();

            var nativeOverlapped = overlapped.UnsafePack((errorCode, numBytes, pOVERLAP) =>
            {
                Debug.WriteLine("Server: http.sys disconnect callback fired for connection ID: " + connectionId);

                // Free the overlapped
                Overlapped.Free(pOVERLAP);

                // Pull the token out of the list and Cancel it.
                Lazy <CancellationToken> token;
                _connectionCancellationTokens.TryRemove(connectionId, out token);
                cts.Cancel();
            },
                                                         null);

            uint hr = NativeMethods.HttpWaitForDisconnect(_requestQueueHandle, connectionId, nativeOverlapped);

            if (hr != NativeMethods.HttpErrors.ERROR_IO_PENDING &&
                hr != NativeMethods.HttpErrors.NO_ERROR)
            {
                // We got an unknown result so return a None
                Debug.WriteLine("Unable to register disconnect callback");
                return(CancellationToken.None);
            }

            return(cts.Token);
        }
Example #2
0
        public unsafe void Execute(UdpSocketSendResult target)
        {
            target.Pin(buffer.Data);

            Overlapped overlapped = new Overlapped {
                AsyncResult = target
            };
            NativeOverlapped *native    = overlapped.UnsafePack(null, null);
            IntPtr            reference = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Data, buffer.Offset);

            TcpSocketInterop.WSABuffer data = new TcpSocketInterop.WSABuffer
            {
                length = buffer.Count,
                buffer = reference
            };

            byte[] address       = endpoint.Address.GetAddressBytes();
            byte[] addressData   = { 0x02, 0x00, (byte)(endpoint.Port / 256), (byte)(endpoint.Port % 256), address[0], address[1], address[2], address[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            IntPtr addressBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(addressData, 0);

            target.Pin(addressData);

            int  written;
            uint result = UdpSocketInterop.WSASendTo(handle, &data, 1, out written, 0, addressBuffer, addressData.Length, native, IntPtr.Zero);
            uint error  = TcpSocketInterop.WSAGetLastError();

            if (result != 0 && error != 997)
            {
                target.Fail(error);
            }
        }
Example #3
0
        public unsafe void Execute(TcpSocketDisconnectResult target)
        {
            int    sent;
            IntPtr ptr    = IntPtr.Zero;
            Guid   guid   = new Guid("{0x7fda2e11,0x8630,0x436f,{0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}} ");
            int    result = TcpSocketInterop.WSAIoctl(handle, unchecked ((int)0xC8000006), ref guid, sizeof(Guid), out ptr, sizeof(IntPtr), out sent, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                throw new Exception();
            }

            TcpSocketInterop.DisconnectExDelegate disconnect = (TcpSocketInterop.DisconnectExDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(TcpSocketInterop.DisconnectExDelegate));
            Overlapped overlapped = new Overlapped {
                AsyncResult = target
            };
            NativeOverlapped *native = overlapped.UnsafePack(null, null);

            result = disconnect.Invoke(handle, native, 0x02, 0);
            uint error = TcpSocketInterop.GetLastError();

            if (result == 0 && error != 997)
            {
                target.Fail(error);
            }
        }
        /// <summary>
        /// <see cref="IDevice.ReadAsync(int, ulong, IntPtr, uint, IOCompletionCallback, IAsyncResult)">Inherited</see>
        /// </summary>
        public override unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            // It is up to the allocator to make sure no reads are issued to segments before they are written
            if (!blobs.TryGetValue(segmentId, out BlobEntry blobEntry))
            {
                throw new InvalidOperationException("Attempting to read non-existent segments");
            }

            // Even though Azure Page Blob does not make use of Overlapped, we populate one to conform to the callback API
            Overlapped        ov       = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero);

            UnmanagedMemoryStream stream   = new UnmanagedMemoryStream((byte *)destinationAddress, readLength, readLength, FileAccess.Write);
            CloudPageBlob         pageBlob = blobEntry.GetPageBlob();

            pageBlob.BeginDownloadRangeToStream(stream, (Int64)sourceAddress, readLength, ar => {
                try
                {
                    pageBlob.EndDownloadRangeToStream(ar);
                }
                // I don't think I can be more specific in catch here because no documentation on exception behavior is provided
                catch (Exception e)
                {
                    Trace.TraceError(e.Message);
                    // Is there any documentation on the meaning of error codes here? The handler suggests that any non-zero value is an error
                    // but does not distinguish between them.
                    callback(2, readLength, ovNative);
                }
                callback(0, readLength, ovNative);
            }, asyncResult);
        }
        internal void Pack(object pinnedObjects)
        {
            if (this.nativeOverlapped != null)
            {
                // If we reach this condition, we have a bug in a derived AsyncResult class.
                // It attempted to initiate a new async I/O operation before the previous
                // one completed. This is a fatal condition, so we cannot continue execution.
                DiagnosticUtility.FailFast("Must allow previous I/O to complete before packing");
            }

            GC.ReRegisterForFinalize(this);

            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this);

            if (this.callback == null)
            {
                this.nativeOverlapped = overlapped.UnsafePack(
                    IOCompletionCallback,
                    pinnedObjects);
            }
            else
            {
                this.nativeOverlapped = overlapped.Pack(
                    IOCompletionCallback,
                    pinnedObjects);
            }
        }
Example #6
0
        public unsafe void Execute(FileWriteResult target)
        {
            target.Pin(buffer.Data);

            Overlapped overlapped = new Overlapped
            {
                AsyncResult = target,
                OffsetLow   = (int)(target.Position & 0xffffffff),
                OffsetHigh  = (int)((target.Position >> 32) & 0xffffffff)
            };

            NativeOverlapped *native = overlapped.UnsafePack(null, null);
            IntPtr            array  = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Data, buffer.Offset);

            int  read;
            int  result = FileInterop.WriteFile(handle, array, buffer.Count, out read, native);
            uint error  = FileInterop.GetLastError();

            if (result == 0 && error != 997)
            {
                target.Fail(error);
            }

            if (result == 1)
            {
                target.Complete(native, read);
            }
        }
Example #7
0
        private unsafe void SignalWorkerThreadsToStop()
        {
            Observable.Interval(TimeSpan.FromMilliseconds(25))
            .TakeWhile(_ => _runningThreads > 0)
            .Select(_ =>
            {
                var result = new SwatcherAsyncResult {
                    Buffer = new byte[0]
                };
                var overlapped = new Overlapped {
                    AsyncResult = result
                };

                //the first parameter is null because we're not using IO completion callbacks; they're too slow.
                //we're taking the byte array from our empty byte array and passing that as user data to the overlapped.
                var overlappedPointer = overlapped.UnsafePack(null, result.Buffer);
                //when using IOCPs, we can send our own custom messages to the GetQueuedCompletionStatus
                //method by call PostQueuedCompletionStatus. In this case, we want to stop the threads that are
                //waiting on change events, so we will send a custom completion key "StopIocpThreads".
                WindowsFacade.PostQueuedCompletionStatus(CompletionPortHandle, 0, StopIocpThreads, overlappedPointer);
                return(Unit.Default);
            })
            .AsCompletion()
            .Where(_ => Config.LoggingEnabled)
            .Subscribe(_ =>
            {
                Disposables.Dispose();
                Logger.Info("Swatcher has stopped");
            });
        }
        public unsafe void Execute(UdpSocketReceiveResult target)
        {
            target.Pin(buffer.Data);

            IntPtr     array      = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Data, buffer.Offset);
            Overlapped overlapped = new Overlapped {
                AsyncResult = target
            };
            NativeOverlapped *native = overlapped.UnsafePack(null, null);

            TcpSocketInterop.WSABuffer data = new TcpSocketInterop.WSABuffer
            {
                length = buffer.Count,
                buffer = array
            };

            byte[] addressData    = new byte[16];
            IntPtr addressPointer = Marshal.UnsafeAddrOfPinnedArrayElement(addressData, 0);

            target.Address = addressData;
            target.Pin(addressData);

            int  read, flags = 0, size = addressData.Length;
            int  result = UdpSocketInterop.WSARecvFrom(handle, &data, 1, out read, ref flags, addressPointer, ref size, native, IntPtr.Zero);
            uint error  = TcpSocketInterop.GetLastError();

            if (result == -1 && error != 997)
            {
                target.Fail(error);
            }
        }
            public unsafe void Callback(IAsyncResult result)
            {
                memory.Return();
                Overlapped ov = new Overlapped(0, 0, IntPtr.Zero, asyncResult);

                callback(0, 0, ov.UnsafePack(callback, IntPtr.Zero));
            }
Example #10
0
            public unsafe OverlappedIOCallback(WaitCallback callback, ExceptionCallback exceptionCallback)
            {
                Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, null);

                this.nativeOverlapped = overlapped.UnsafePack(new IOCompletionThunk(this.IOCallback, exceptionCallback).ThunkFrame, null);
                this.callback         = callback;
            }
Example #11
0
        //---- the overridden methods represent the interface for a generic storage device

        /// <summary>
        /// <see cref="IDevice.ReadAsync(int, ulong, IntPtr, uint, IOCompletionCallback, IAsyncResult)">Inherited</see>
        /// </summary>
        public override unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            Debug.WriteLine($"AzureStorageDevice.ReadAsync Called segmentId={segmentId} sourceAddress={sourceAddress} readLength={readLength}");

            // It is up to the allocator to make sure no reads are issued to segments before they are written
            if (!blobs.TryGetValue(segmentId, out BlobEntry blobEntry))
            {
                var nonLoadedBlob = this.blobDirectory.GetPageBlobReference(GetSegmentBlobName(segmentId));
                var exception     = new InvalidOperationException("Attempt to read a non-loaded segment");
                this.BlobManager?.HandleBlobError(nameof(ReadAsync), exception.Message, nonLoadedBlob?.Name, exception, true);
                throw exception;
            }

            // Even though Azure Page Blob does not make use of Overlapped, we populate one to conform to the callback API
            Overlapped        ov       = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero);

            this.ReadFromBlobUnsafeAsync(blobEntry.PageBlob, (long)sourceAddress, (long)destinationAddress, readLength)
            .ContinueWith((Task t) =>
            {
                if (t.IsFaulted)
                {
                    Debug.WriteLine("AzureStorageDevice.ReadAsync Returned (Failure)");
                    callback(uint.MaxValue, readLength, ovNative);
                }
                else
                {
                    Debug.WriteLine("AzureStorageDevice.ReadAsync Returned");
                    callback(0, readLength, ovNative);
                }
            });
        }
Example #12
0
        public void ReadAsync(ulong alignedSourceAddress, IntPtr alignedDestinationAddress, uint aligned_read_length, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            long logicalAddress = (long)alignedSourceAddress;
            long page           = logicalAddress >> PageSizeBits;
            int  pageIndex      = (int)(page % BufferSize);

            Debug.Assert(page == pageIndex);

            Overlapped        ov        = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ov_native = ov.UnsafePack(callback, IntPtr.Zero);

            ov_native->OffsetLow  = unchecked ((int)(alignedSourceAddress & 0xFFFFFFFF));
            ov_native->OffsetHigh = unchecked ((int)((alignedSourceAddress >> 32) & 0xFFFFFFFF));

            if (values[pageIndex] == null)
            {
                callback(2, 0, ov_native);
            }
            else
            {
                long physicalAddress = GetPhysicalAddress(logicalAddress);
                Utility.Copy((byte *)physicalAddress, (byte *)alignedDestinationAddress, (int)aligned_read_length);
                callback(0, aligned_read_length, ov_native);
            }
        }
Example #13
0
        public unsafe void Execute(TcpSocketSendResult target)
        {
            target.Pin(buffer.Data);

            Overlapped overlapped = new Overlapped {
                AsyncResult = target
            };
            NativeOverlapped *native    = overlapped.UnsafePack(null, null);
            IntPtr            reference = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Data, buffer.Offset);

            TcpSocketInterop.WSABuffer data = new TcpSocketInterop.WSABuffer
            {
                length = buffer.Count,
                buffer = reference
            };

            int  written;
            uint result = TcpSocketInterop.WSASend(handle, &data, 1, out written, 0, native, IntPtr.Zero);
            uint error  = TcpSocketInterop.WSAGetLastError();

            if (result != 0 && error != 997)
            {
                target.Fail(error);
            }
        }
Example #14
0
        public void WriteAsync(IntPtr alignedSourceAddress, ulong alignedDestinationAddress, uint numBytesToWrite, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            long logicalAddress = (long)alignedDestinationAddress;
            long page           = logicalAddress >> PageSizeBits;
            int  pageIndex      = (int)(page % BufferSize);

            Debug.Assert(page == pageIndex);

            if (values[pageIndex] == null)
            {
                // Allocate a new page
                AllocatePage(pageIndex);
            }
            else
            {
                //Clear an old used page
                Array.Clear(values[pageIndex], 0, values[pageIndex].Length);
            }

            long physicalAddress = GetPhysicalAddress(logicalAddress);

            Utility.Copy((byte *)alignedSourceAddress, (byte *)physicalAddress, (int)numBytesToWrite);

            Overlapped        ov        = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ov_native = ov.UnsafePack(callback, IntPtr.Zero);

            ov_native->OffsetLow  = unchecked ((int)(alignedDestinationAddress & 0xFFFFFFFF));
            ov_native->OffsetHigh = unchecked ((int)((alignedDestinationAddress >> 32) & 0xFFFFFFFF));

            callback(0, numBytesToWrite, ov_native);
        }
            public unsafe void Callback(IAsyncResult result)
            {
                if (errorCode == 0)
                {
                    try
                    {
                        logHandle.EndRead(result);
                        fixed(void *source = memory.buffer)
                        {
                            Buffer.MemoryCopy(source, (void *)destinationAddress, readLength, readLength);
                        }
                    }
                    catch (IOException e)
                    {
                        errorCode = (uint)(e.HResult & 0x0000FFFF);
                    }
                    catch
                    {
                        // Non-IO exception; assign error code of max value
                        errorCode = uint.MaxValue;
                    }
                }

                memory.Return();
                Overlapped ov = new Overlapped(0, 0, IntPtr.Zero, asyncResult);

                callback(errorCode, 0, ov.UnsafePack(callback, IntPtr.Zero));
            }
Example #16
0
        public unsafe void Execute(TcpSocketConnectResult target)
        {
            int    sent;
            IntPtr ptr    = IntPtr.Zero;
            Guid   guid   = new Guid("{0x25a207b9,0x0ddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}");
            int    result = TcpSocketInterop.WSAIoctl(handle, unchecked ((int)0xC8000006), ref guid, sizeof(Guid), out ptr, sizeof(IntPtr), out sent, IntPtr.Zero, IntPtr.Zero);

            if (result != 0)
            {
                throw new Exception();
            }

            byte[] address = endpoint.Address.GetAddressBytes();
            byte[] data    = { 0x02, 0x00, (byte)(endpoint.Port / 256), (byte)(endpoint.Port % 256), address[0], address[1], address[2], address[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            TcpSocketInterop.ConnectExDelegate connectex = (TcpSocketInterop.ConnectExDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(TcpSocketInterop.ConnectExDelegate));

            Overlapped overlapped = new Overlapped {
                AsyncResult = target
            };
            NativeOverlapped *native = overlapped.UnsafePack(null, null);

            target.Pin(data);
            worker.Add(handle);

            IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);

            result = connectex.Invoke(handle, buffer, data.Length, IntPtr.Zero, 0, out sent, native);
            uint error = TcpSocketInterop.GetLastError();

            if (result == 0 && error != 997)
            {
                target.Fail(error);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="sourceAddress"></param>
        /// <param name="segmentId"></param>
        /// <param name="destinationAddress"></param>
        /// <param name="numBytesToWrite"></param>
        /// <param name="callback"></param>
        /// <param name="asyncResult"></param>
        public override unsafe void WriteAsync(IntPtr sourceAddress,
                                               int segmentId,
                                               ulong destinationAddress,
                                               uint numBytesToWrite,
                                               IOCompletionCallback callback,
                                               IAsyncResult asyncResult)
        {
            var logHandle = GetOrAddHandle(segmentId);

            Overlapped        ov       = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero);

            ovNative->OffsetLow  = unchecked ((int)(destinationAddress & 0xFFFFFFFF));
            ovNative->OffsetHigh = unchecked ((int)((destinationAddress >> 32) & 0xFFFFFFFF));

            bool result = Native32.WriteFile(logHandle,
                                             sourceAddress,
                                             numBytesToWrite,
                                             out uint bytesWritten,
                                             ovNative);

            if (!result)
            {
                int error = Marshal.GetLastWin32Error();
                if (error != Native32.ERROR_IO_PENDING)
                {
                    Overlapped.Unpack(ovNative);
                    Overlapped.Free(ovNative);
                    throw new Exception("Error writing to log file: " + error);
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="sourceAddress"></param>
        /// <param name="destinationAddress"></param>
        /// <param name="readLength"></param>
        /// <param name="callback"></param>
        /// <param name="asyncResult"></param>
        public override unsafe void ReadAsync(int segmentId, ulong sourceAddress,
                                              IntPtr destinationAddress,
                                              uint readLength,
                                              IOCompletionCallback callback,
                                              IAsyncResult asyncResult)
        {
            var logHandle = GetOrAddHandle(segmentId);

            Overlapped        ov       = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero);

            ovNative->OffsetLow  = unchecked ((int)((ulong)sourceAddress & 0xFFFFFFFF));
            ovNative->OffsetHigh = unchecked ((int)(((ulong)sourceAddress >> 32) & 0xFFFFFFFF));

            bool result = Native32.ReadFile(logHandle,
                                            destinationAddress,
                                            readLength,
                                            out uint bytesRead,
                                            ovNative);

            if (!result)
            {
                int error = Marshal.GetLastWin32Error();
                if (error != Native32.ERROR_IO_PENDING)
                {
                    Overlapped.Unpack(ovNative);
                    Overlapped.Free(ovNative);
                    throw new Exception("Error reading from log file: " + error);
                }
            }
        }
Example #19
0
        /// <summary>
        /// Create instance, automatically allocates NativeOverlapped structure
        /// </summary>
        /// <param name="callback">User specified callback</param>
        /// <param name="state">User specified state</param>
        /// <param name="fileOffset">Start position</param>
        /// <param name="userData">An object or array of objects representing the input or output buffer for the operation. Buffer is pinned until object is disposed.</param>
        public AsyncJob(AsyncCallback callback, object state, UInt64 fileOffset, object userData)
        {
            _callback = callback;
            _state    = state;
            Overlapped ov = new Overlapped(unchecked ((int)(fileOffset & 0xFFFFFFFF)), unchecked ((int)((fileOffset >> 32) & 0xFFFFFFFF)), IntPtr.Zero, this);

            unsafe { _nativeOverlapped = ov.UnsafePack(completionCallback, userData); }
        }
Example #20
0
        public unsafe LogWriterWindows(string fileName,
                                       uint chunkSize,
                                       uint maxChunksPerWrite,
                                       bool appendOpen = false)
        {
            //Console.WriteLine("64-bitness: " + Environment.Is64BitProcess);
            _lastError       = 0;
            _allocationUnit  = 1024 * 1024 * 512;
            _allocations     = 0;
            _writesFinished  = 1;
            _writesFinishedQ = new AsyncQueue <int>();
            _bufSize         = maxChunksPerWrite * chunkSize + sectorSize;
            _buf             = new BytePtrWrapper();
            var tempBuf = new byte[_bufSize];

            _buf._handle = GCHandle.Alloc(tempBuf, GCHandleType.Pinned);
            _buf._ptr    = (byte *)_buf._handle.AddrOfPinnedObject();

            _IOThreadInfo      = new IOThreadState[maxChunksPerWrite];
            _IOThreadInfoAsync = new IOThreadState[maxChunksPerWrite];
            var filePointer = new LocalStorageDevice(fileName, true, false, true);

            for (int i = 0; i < maxChunksPerWrite; i++)
            {
                var job      = new AsyncJob();
                var jobAsync = new AsyncJob();
                var ov       = new Overlapped(0, 0, IntPtr.Zero, job);
                var ovAsync  = new Overlapped(0, 0, IntPtr.Zero, jobAsync);
                NativeOverlapped *ov_native      = ov.UnsafePack(FlushCallback, IntPtr.Zero);
                NativeOverlapped *ov_nativeAsync = ovAsync.UnsafePack(FlushAsyncCallBack, IntPtr.Zero);
                Thread.Sleep(10);
                var myIOThreadState = new IOThreadState();
                myIOThreadState.filePointer = filePointer;
                myIOThreadState.ov_native   = ov_native;
                _IOThreadInfo[i]            = myIOThreadState;
                var myIOThreadStateAsync = new IOThreadState();
                myIOThreadStateAsync.filePointer = filePointer;
                myIOThreadStateAsync.ov_native   = ov_nativeAsync;
                _IOThreadInfoAsync[i]            = myIOThreadStateAsync;
            }
            _bufBytesOccupied  = 0;
            _chunkSize         = chunkSize;
            _maxChunksPerWrite = maxChunksPerWrite;
            if (!appendOpen)
            {
                _fileSize = 0;
                _filePos  = 0;
            }
            else
            {
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!inefficient workaround until Badrish adds a filesize call
                using (var fileReader = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    _fileSize = _filePos = (ulong)fileReader.Length;
                }
            }
            _outstandingWrites = 0;
        }
Example #21
0
        static unsafe void Main(string[] args)
        {
            // create completion port
            var completionPortHandle = Interop.CreateIoCompletionPort(new IntPtr(-1), IntPtr.Zero, 0, 0);

            ThreadLogger.Log("Completion port handle: {0}", completionPortHandle);

            var completionPortThread = new Thread(() => new IOCompletionWorker().Start(completionPortHandle))
            {
                IsBackground = true
            };

            completionPortThread.Start();

            const uint Flags = 128 | (uint)1 << 30;

            var fileHandle = Interop.CreateFile("test.txt", (uint)1 << 31, 0, IntPtr.Zero, 3,
                                                /*FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED */ Flags,
                                                IntPtr.Zero);

            ThreadLogger.Log("File handle: {0}", fileHandle);

            Interop.CreateIoCompletionPort(
                fileHandle,
                completionPortHandle,
                (uint)fileHandle.ToInt64(),
                0);

            ThreadLogger.Log("Associated file handle with completion port");

            var readBuffer = new byte[1024];

            uint bytesRead;

            var overlapped = new Overlapped
            {
                AsyncResult = new FileReadAsyncResult()
                {
                    ReadCallback = (bytesCount, buffer) =>
                    {
                        var contentRead = Encoding.UTF8.GetString(buffer, 0, (int)bytesCount);
                        ThreadLogger.Log(contentRead);
                    },
                    Buffer = readBuffer
                }
            };

            NativeOverlapped *nativeOverlapped = overlapped.UnsafePack(null, readBuffer);

            ThreadLogger.Log("Before read in main thread");

            Interop.ReadFile(fileHandle, readBuffer, (uint)readBuffer.Length, out bytesRead, nativeOverlapped);

            ThreadLogger.Log("After read in main thread");

            Console.ReadLine();
        }
Example #22
0
        public unsafe void WriteAsync(IntPtr alignedSourceAddress, ulong alignedDestinationAddress, uint numBytesToWrite, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            Overlapped        ov        = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ov_native = ov.UnsafePack(callback, IntPtr.Zero);

            ov_native->OffsetLow  = unchecked ((int)(alignedDestinationAddress & 0xFFFFFFFF));
            ov_native->OffsetHigh = unchecked ((int)((alignedDestinationAddress >> 32) & 0xFFFFFFFF));

            callback(0, numBytesToWrite, ov_native);
        }
Example #23
0
        internal OverlappedCache(Overlapped overlapped, object pinnedObjects, IOCompletionCallback callback, bool alreadyTriedCast)
        {
            m_Overlapped         = overlapped;
            m_PinnedObjects      = pinnedObjects;
            m_PinnedObjectsArray = alreadyTriedCast ? null : NclConstants.EmptyObjectArray;

            unsafe
            {
                m_NativeOverlapped = (IntPtr)overlapped.UnsafePack(callback, pinnedObjects);
            }
        }
Example #24
0
        internal OverlappedCache(Overlapped overlapped, object[] pinnedObjectsArray, IOCompletionCallback callback)
        {
            m_Overlapped         = overlapped;
            m_PinnedObjects      = pinnedObjectsArray;
            m_PinnedObjectsArray = pinnedObjectsArray;

            unsafe
            {
                m_NativeOverlapped = (IntPtr)overlapped.UnsafePack(callback, pinnedObjectsArray);
            }
        }
Example #25
0
        public unsafe void ReadAsync(int segmentId, ulong alignedSourceAddress, IntPtr alignedDestinationAddress, uint aligned_read_length, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            alignedSourceAddress = ((ulong)segmentId << _segmentSizeBits) | alignedSourceAddress;

            Overlapped        ov        = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
            NativeOverlapped *ov_native = ov.UnsafePack(callback, IntPtr.Zero);

            ov_native->OffsetLow  = unchecked ((int)(alignedSourceAddress & 0xFFFFFFFF));
            ov_native->OffsetHigh = unchecked ((int)((alignedSourceAddress >> 32) & 0xFFFFFFFF));

            callback(0, aligned_read_length, ov_native);
        }
Example #26
0
        /// <summary>
        /// <see cref="IDevice.WriteAsync(IntPtr, int, ulong, uint, IOCompletionCallback, IAsyncResult)"/>
        /// </summary>
        /// <param name="sourceAddress"></param>
        /// <param name="segmentId"></param>
        /// <param name="destinationAddress"></param>
        /// <param name="numBytesToWrite"></param>
        /// <param name="callback"></param>
        /// <param name="asyncResult"></param>
        public unsafe override void WriteAsync(IntPtr sourceAddress, int segmentId, ulong destinationAddress, uint numBytesToWrite, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            // Starts off in one, in order to prevent some issued writes calling the callback before all parallel writes are issued.
            var  countdown          = new CountdownEvent(1);
            long currentWriteStart  = (long)destinationAddress;
            long writeEnd           = currentWriteStart + (long)numBytesToWrite;
            uint aggregateErrorCode = 0;

            while (currentWriteStart < writeEnd)
            {
                long  newStart    = partitions.MapRange(currentWriteStart, writeEnd, out int shard, out long shardStartAddress, out long shardEndAddress);
                ulong writeOffset = (ulong)currentWriteStart - destinationAddress;
                // Indicate that there is one more task to wait for
                countdown.AddCount();
                // Because more than one device can return with an error, it is important that we remember the most recent error code we saw. (It is okay to only
                // report one error out of many. It will be as if we failed on that error and cancelled all other reads, even though we issue reads in parallel and
                // wait until all of them are complete in the implementation)
                // Can there be races on async result as we issue writes or reads in parallel?
                partitions.Devices[shard].WriteAsync(IntPtr.Add(sourceAddress, (int)writeOffset),
                                                     segmentId,
                                                     (ulong)shardStartAddress,
                                                     (uint)(shardEndAddress - shardStartAddress),
                                                     (e, n, o) =>
                {
                    // TODO: Check if it is incorrect to ignore o
                    if (e != 0)
                    {
                        aggregateErrorCode = e;
                    }
                    if (countdown.Signal())
                    {
                        callback(aggregateErrorCode, n, o);
                        countdown.Dispose();
                    }
                    else
                    {
                        Overlapped.Free(o);
                    }
                },
                                                     asyncResult);

                currentWriteStart = newStart;
            }

            // TODO: Check if overlapped wrapper is handled correctly
            if (countdown.Signal())
            {
                Overlapped        ov       = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
                NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero);
                callback(aggregateErrorCode, numBytesToWrite, ovNative);
                countdown.Dispose();
            }
        }
            public unsafe void Callback(IAsyncResult result)
            {
                fixed(void *source = memory.buffer)
                {
                    Buffer.MemoryCopy(source, (void *)destinationAddress, readLength, readLength);
                }

                memory.Return();
                Overlapped ov = new Overlapped(0, 0, IntPtr.Zero, asyncResult);

                callback(0, 0, ov.UnsafePack(callback, IntPtr.Zero));
            }
Example #28
0
        // ReSharper disable once SuggestVarOrType_Elsewhere
        private static unsafe void WatchFolderForChanges(
            object wrapper, ISwatcherConfig config,
            IWindowsFacade windowsFacade, SafeFileHandle directoryHandle)
        {
            var result = new SwatcherAsyncResult {
                Buffer = new byte[DefaultBufferSize]
            };
            var overlapped = new Overlapped {
                AsyncResult = result
            };

            //the first parameter is null because we're not using IO completion callbacks; they're too slow.
            //we're taking the byte array from our empty byte array and passing that as user data to the overlapped.
            var overlappedPointer = overlapped.UnsafePack(null, result.Buffer);

            var success = false;

            try
            {
                //now we wrap this section in a fixed block to pin it to the original address.
                //we cannot have it move because the OS will write information about the changes
                //into this byte array.
                fixed(byte *bufferPointer = result.Buffer)
                {
                    var bytesReturned = 0;
                    var bufferHandle  = new HandleRef(result, (IntPtr)bufferPointer);
                    var isRecursive   = Convert.ToInt32(config.IsRecursive);

                    //because we're using IO completion ports, we pass our overlapped pointer into this unmanaged
                    //call. when a change has been received, the OS will callback via GetQueuedCompletionStatus
                    //passing the overlapped pointer (which has our IAsyncResult/byte array) back to us.
                    success = windowsFacade.ReadDirectoryChangesW(
                        directoryHandle, bufferHandle, DefaultBufferSize, isRecursive,
                        (int)config.NotificationTypes, bytesReturned, overlappedPointer, SafeLocalMemHandle.Empty);

                    //in this usage of ReadDirectoryChangesW, we should *always* get 0 bytes returned.
                    if (bytesReturned != 0)
                    {
                        Debugger.Break();
                    }
                }
            }
            finally
            {
                //if success is false, our directory handle has likely become invalid. attempt to re-establish it.
                if (!success)
                {
                    Debugger.Break();
                    //before doing anything else, cleanup here to prevent memory leaks.
                    Overlapped.Free(overlappedPointer);
                }
            }
        }
Example #29
0
        /// <summary>
        /// <see cref="IDevice.ReadAsync(int, ulong, IntPtr, uint, IOCompletionCallback, IAsyncResult)"/>
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="sourceAddress"></param>
        /// <param name="destinationAddress"></param>
        /// <param name="readLength"></param>
        /// <param name="callback"></param>
        /// <param name="asyncResult"></param>
        public unsafe override void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, IOCompletionCallback callback, IAsyncResult asyncResult)
        {
            // Starts off in one, in order to prevent some issued writes calling the callback before all parallel writes are issued.
            var  countdown          = new CountdownEvent(1);
            long currentReadStart   = (long)sourceAddress;
            long readEnd            = currentReadStart + readLength;
            uint aggregateErrorCode = 0;

            while (currentReadStart < readEnd)
            {
                long  newStart    = partitions.MapRange(currentReadStart, readEnd, out int shard, out long shardStartAddress, out long shardEndAddress);
                ulong writeOffset = (ulong)currentReadStart - sourceAddress;
                // Because more than one device can return with an error, it is important that we remember the most recent error code we saw. (It is okay to only
                // report one error out of many. It will be as if we failed on that error and cancelled all other reads, even though we issue reads in parallel and
                // wait until all of them are complete in the implementation)
                // TODO(Tianyu): Can there be races on async result as we issue writes or reads in parallel?
                countdown.AddCount();
                partitions.Devices[shard].ReadAsync(segmentId,
                                                    (ulong)shardStartAddress,
                                                    IntPtr.Add(destinationAddress, (int)writeOffset),
                                                    (uint)(shardEndAddress - shardStartAddress),
                                                    (e, n, o) =>
                {
                    // TODO(Tianyu): this is incorrect if returned "bytes" written is allowed to be less than requested like POSIX.
                    if (e != 0)
                    {
                        aggregateErrorCode = e;
                    }
                    if (countdown.Signal())
                    {
                        callback(aggregateErrorCode, n, o);
                        countdown.Dispose();
                    }
                    else
                    {
                        Overlapped.Free(o);
                    }
                },
                                                    asyncResult);

                currentReadStart = newStart;
            }

            // TODO(Tianyu): What do for the dumb overlapped wrapper...
            if (countdown.Signal())
            {
                Overlapped        ov       = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
                NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero);
                callback(aggregateErrorCode, readLength, ovNative);
                countdown.Dispose();
            }
        }
Example #30
0
        private unsafe CancellationToken CreateToken(ulong connectionId)
        {
            // Create a nativeOverlapped callback so we can register for disconnect callback
            var overlapped = new Overlapped();
            var cts        = new CancellationTokenSource();
            CancellationToken returnToken = cts.Token;

            NativeOverlapped *nativeOverlapped = overlapped.UnsafePack(
                (errorCode, numBytes, overlappedPtr) =>
            {
                // Free the overlapped
                Overlapped.Free(overlappedPtr);

                if (errorCode != NativeMethods.HttpErrors.NO_ERROR)
                {
                    LogHelper.LogException(_logger, "IOCompletionCallback", new Win32Exception((int)errorCode));
                }

                // Pull the token out of the list and Cancel it.
                ConnectionCancellation cancellation;
                _connectionCancellationTokens.TryRemove(connectionId, out cancellation);

                bool success = ThreadPool.UnsafeQueueUserWorkItem(CancelToken, cts);
                Debug.Assert(success, "Unable to queue disconnect notification.");
            },
                null);

            uint hr = NativeMethods.HttpWaitForDisconnectEx(_requestQueueHandle, connectionId, 0, nativeOverlapped);

            if (hr != NativeMethods.HttpErrors.ERROR_IO_PENDING &&
                hr != NativeMethods.HttpErrors.NO_ERROR)
            {
                // We got an unknown result, assume the connection has been closed.
                Overlapped.Free(nativeOverlapped);
                ConnectionCancellation cancellation;
                _connectionCancellationTokens.TryRemove(connectionId, out cancellation);
                LogHelper.LogException(_logger, "HttpWaitForDisconnectEx", new Win32Exception((int)hr));
                cts.Cancel();
            }

            if (hr == NativeMethods.HttpErrors.NO_ERROR && SkipIOCPCallbackOnSuccess)
            {
                // IO operation completed synchronously - callback won't be called to signal completion
                Overlapped.Free(nativeOverlapped);
                ConnectionCancellation cancellation;
                _connectionCancellationTokens.TryRemove(connectionId, out cancellation);
                cts.Cancel();
            }

            return(returnToken);
        }
Example #31
0
        unsafe private FileStreamAsyncResult BeginWriteCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
        { 
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed"); 
            Contract.Assert(CanWrite, "CanWrite");
            Contract.Assert(bytes != null, "bytes != null"); 
            Contract.Assert(_readPos == _readLen, "_readPos == _readLen");
            Contract.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(numBytes >= 0, "numBytes is negative"); 

            // Create and store async stream class library specific data in the 
            // async result 
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult();
            asyncResult._handle = _handle; 
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject;
            asyncResult._isWrite = true;
 
            // For Synchronous IO, I could go with either a callback and using
            // the managed Monitor class, or I could create a handle and wait on it. 
            ManualResetEvent waitHandle = new ManualResetEvent(false); 
            asyncResult._waitHandle = waitHandle;
 
            // Create a managed overlapped class
            // We will set the file offsets later
            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult);
 
            // Pack the Overlapped class, and store it in the async result
            NativeOverlapped* intOverlapped; 
            if (userCallback != null) 
                intOverlapped = overlapped.Pack(IOCallback, bytes);
            else 
                intOverlapped = overlapped.UnsafePack(null, bytes);
            asyncResult._overlapped = intOverlapped;

            if (CanSeek) { 
                // Make sure we set the length of the file appropriately.
                long len = Length; 
                //Console.WriteLine("BeginWrite - Calculating end pos.  pos: "+pos+"  len: "+len+"  numBytes: "+numBytes); 

                // Make sure we are writing to the position that we think we are 
                if (_exposedHandle)
                    VerifyOSHandlePosition();

                if (_pos + numBytes > len) { 
                    //Console.WriteLine("BeginWrite - Setting length to: "+(pos + numBytes));
                    SetLengthCore(_pos + numBytes); 
                } 

                // Now set the position to read from in the NativeOverlapped struct 
                // For pipes, we should leave the offset fields set to 0.
                intOverlapped->OffsetLow = (int)_pos;
                intOverlapped->OffsetHigh = (int)(_pos>>32);
 
                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it 
                // ourselves.  This isn't threadsafe. 

                // 



 

 
 
                SeekCore(numBytes, SeekOrigin.Current);
            } 

            //Console.WriteLine("BeginWrite finishing.  pos: "+pos+"  numBytes: "+numBytes+"  _pos: "+_pos+"  Position: "+Position);

            int hr = 0; 
            // queue an async WriteFile operation and pass in a packed overlapped
            int r = WriteFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); 
 
            // WriteFile, the OS version, will return 0 on failure.  But
            // my WriteFileNative wrapper returns -1.  My wrapper will return 
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // On async requests that completed sequentially, r==0 
            // You will NEVER RELIABLY be able to get the number of bytes
            // written back from this call when using overlapped IO!  You must 
            // not pass in a non-null lpNumBytesWritten to WriteFile when using 
            // overlapped structures!  This is ByDesign NT behavior.
            if (r==-1 && numBytes!=-1) { 
                //Console.WriteLine("WriteFile returned 0;  Write will complete asynchronously (if hr==3e5)  hr: 0x{0:x}", hr);

                // For pipes, when they are closed on the other side, they will come here.
                if (hr == ERROR_NO_DATA) { 
                    // Not an error, but EOF.  AsyncFSCallback will NOT be
                    // called.  Call the user callback here. 
                    asyncResult.CallUserCallback(); 
                    // EndWrite will free the Overlapped struct correctly.
                } 
                else if (hr != ERROR_IO_PENDING) {
                    if (!_handle.IsClosed && CanSeek)  // Update Position - It could be anywhere.
                        SeekCore(0, SeekOrigin.Current);
 
                    if (hr == ERROR_HANDLE_EOF)
                        __Error.EndOfFile(); 
                    else 
                        __Error.WinIOError(hr, String.Empty);
                } 
            }
            else {
                // Due to a workaround for a race condition in NT's ReadFile &
                // WriteFile routines, we will always be returning 0 from WriteFileNative 
                // when we do async IO instead of the number of bytes written,
                // irregardless of whether the operation completed 
                // synchronously or asynchronously.  We absolutely must not 
                // set asyncResult._numBytes here, since will never have correct
                // results. 
                //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+")  The IO completed synchronously, but the user callback was called on another thread.");
            }

            return asyncResult; 
        }
Example #32
0
        unsafe private FileStreamAsyncResult BeginReadCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead)
        { 
            Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
            Contract.Assert(CanRead, "CanRead"); 
            Contract.Assert(bytes != null, "bytes != null"); 
            Contract.Assert(_writePos == 0, "_writePos == 0");
            Contract.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!"); 
            Contract.Assert(offset >= 0, "offset is negative");
            Contract.Assert(numBytes >= 0, "numBytes is negative");

            // Create and store async stream class library specific data in the 
            // async result
            FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(); 
            asyncResult._handle = _handle; 
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject; 
            asyncResult._isWrite = false;

            // Must set this here to ensure all the state on the IAsyncResult
            // object is set before we call ReadFile, which gives the OS an 
            // opportunity to run our callback (including the user callback &
            // the call to EndRead) before ReadFile has returned. 
            asyncResult._numBufferedBytes = numBufferedBytesRead; 

            // For Synchronous IO, I could go with either a callback and using 
            // the managed Monitor class, or I could create a handle and wait on it.
            ManualResetEvent waitHandle = new ManualResetEvent(false);
            asyncResult._waitHandle = waitHandle;
 
            // Create a managed overlapped class
            // We will set the file offsets later 
            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult); 

            // Pack the Overlapped class, and store it in the async result 
            NativeOverlapped* intOverlapped;
            if (userCallback != null)
                intOverlapped = overlapped.Pack(IOCallback, bytes);
            else 
                intOverlapped = overlapped.UnsafePack(null, bytes);
 
            asyncResult._overlapped = intOverlapped; 

            // Calculate position in the file we should be at after the read is done 
            if (CanSeek) {
                long len = Length;

                // Make sure we are reading from the position that we think we are 
                if (_exposedHandle)
                    VerifyOSHandlePosition(); 
 
                if (_pos + numBytes > len) {
                    if (_pos <= len) 
                        numBytes = (int) (len - _pos);
                    else
                        numBytes = 0;
                } 

                // Now set the position to read from in the NativeOverlapped struct 
                // For pipes, we should leave the offset fields set to 0. 
                intOverlapped->OffsetLow = unchecked((int)_pos);
                intOverlapped->OffsetHigh = (int)(_pos>>32); 

                // When using overlapped IO, the OS is not supposed to
                // touch the file pointer location at all.  We will adjust it
                // ourselves. This isn't threadsafe. 

                // WriteFile should not update the file pointer when writing 
                // in overlapped mode, according to MSDN.  But it does update 
                // the file pointer when writing to a UNC path!
                // So changed the code below to seek to an absolute 
                // location, not a relative one.  ReadFile seems consistent though.
                SeekCore(numBytes, SeekOrigin.Current);
            }
 
            // queue an async ReadFile operation and pass in a packed overlapped
            int hr = 0; 
            int r = ReadFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr); 
            // ReadFile, the OS version, will return 0 on failure.  But
            // my ReadFileNative wrapper returns -1.  My wrapper will return 
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // on async requests that completed sequentially, r==0 
            // You will NEVER RELIABLY be able to get the number of bytes
            // read back from this call when using overlapped structures!  You must 
            // not pass in a non-null lpNumBytesRead to ReadFile when using 
            // overlapped structures!  This is by design NT behavior.
            if (r==-1 && numBytes!=-1) { 

                // For pipes, when they hit EOF, they will come here.
                if (hr == ERROR_BROKEN_PIPE) {
                    // Not an error, but EOF.  AsyncFSCallback will NOT be 
                    // called.  Call the user callback here.
 
                    // We clear the overlapped status bit for this special case. 
                    // Failure to do so looks like we are freeing a pending overlapped later.
                    intOverlapped->InternalLow = IntPtr.Zero; 
                    asyncResult.CallUserCallback();
                    // EndRead will free the Overlapped struct correctly.
                }
                else if (hr != ERROR_IO_PENDING) { 
                    if (!_handle.IsClosed && CanSeek)  // Update Position - It could be anywhere.
                        SeekCore(0, SeekOrigin.Current); 
 
                    if (hr == ERROR_HANDLE_EOF)
                        __Error.EndOfFile(); 
                    else
                        __Error.WinIOError(hr, String.Empty);
                }
            } 
            else {
                // Due to a workaround for a race condition in NT's ReadFile & 
                // WriteFile routines, we will always be returning 0 from ReadFileNative 
                // when we do async IO instead of the number of bytes read,
                // irregardless of whether the operation completed 
                // synchronously or asynchronously.  We absolutely must not
                // set asyncResult._numBytes here, since will never have correct
                // results.
                //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+")  The IO completed synchronously, but the user callback was called on a separate thread"); 
            }
 
            return asyncResult; 
        }