/// <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); } } }
/// <summary> /// Async read /// </summary> /// <param name="segmentId"></param> /// <param name="sourceAddress"></param> /// <param name="destinationAddress"></param> /// <param name="readLength"></param> /// <param name="callback"></param> /// <param name="context"></param> public override void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, DeviceIOCompletionCallback callback, object context) { if (!results.TryDequeue(out SimpleAsyncResult result)) { result = new SimpleAsyncResult(); result.overlapped = new Overlapped(0, 0, IntPtr.Zero, result); result.nativeOverlapped = result.overlapped.UnsafePack(_callback, IntPtr.Zero); } result.context = context; result.callback = callback; var ovNative = result.nativeOverlapped; ovNative->OffsetLow = unchecked ((int)((ulong)sourceAddress & 0xFFFFFFFF)); ovNative->OffsetHigh = unchecked ((int)(((ulong)sourceAddress >> 32) & 0xFFFFFFFF)); try { var logHandle = GetOrAddHandle(segmentId); Interlocked.Increment(ref numPending); bool _result = Native32.ReadFile(logHandle, destinationAddress, readLength, out uint bytesRead, ovNative); if (!_result) { int error = Marshal.GetLastWin32Error(); if (error != Native32.ERROR_IO_PENDING) { throw new IOException("Error reading from log file", error); } } } catch (IOException e) { Interlocked.Decrement(ref numPending); callback((uint)(e.HResult & 0x0000FFFF), 0, context); results.Enqueue(result); } catch { Interlocked.Decrement(ref numPending); callback(uint.MaxValue, 0, context); results.Enqueue(result); } }
public unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, IAsyncResult asyncResult) { var logHandle = GetOrAddHandle(segmentId); Overlapped ov = new Overlapped { AsyncResult = asyncResult, OffsetLow = unchecked ((int)(sourceAddress & 0xFFFFFFFF)), OffsetHigh = unchecked ((int)((sourceAddress >> 32) & 0xFFFFFFFF)) }; NativeOverlapped *ovNative = ov.UnsafePack(null, IntPtr.Zero); /* Invoking the Native method ReadFile provided by Kernel32.dll * library. Returns false, if request failed or accepted for async * operation. Returns true, if success synchronously. */ uint bytesRead = default(uint); bool result = Native32.ReadFile(logHandle, destinationAddress, readLength, out bytesRead, ovNative); if (!result) { int error = Marshal.GetLastWin32Error(); /* Just handle the case when it is not ERROR_IO_PENDING * If ERROR_IO_PENDING, then it is accepted for async execution */ if (error != Native32.ERROR_IO_PENDING) { Overlapped.Unpack(ovNative); Overlapped.Free(ovNative); throw new Exception("Error reading from log file: " + error); } } else { //executed synchronously, so process callback //callback(0, bytesRead, ovNative); } }
public unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, IOCompletionCallback callback, IAsyncResult asyncResult) { var logHandle = GetOrAddHandle(segmentId); //Debug.WriteLine("sourceAddress: {0}, destinationAddress: {1}, readLength: {2}" // , sourceAddress, (ulong)destinationAddress, readLength); if (readLength != 512) { } 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)); uint bytesRead = default(uint); bool result = Native32.ReadFile(logHandle, destinationAddress, readLength, out bytesRead, ovNative); if (!result) { int error = Marshal.GetLastWin32Error(); if (error != Native32.ERROR_IO_PENDING) { Overlapped.Unpack(ovNative); Overlapped.Free(ovNative); // NOTE: alignedDestinationAddress needs to be freed by whoever catches the exception throw new Exception("Error reading from log file: " + error); } } else { // On synchronous completion, issue callback directly callback(0, bytesRead, ovNative); } }