/// <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="sourceAddress"></param> /// <param name="segmentId"></param> /// <param name="destinationAddress"></param> /// <param name="numBytesToWrite"></param> /// <param name="callback"></param> /// <param name="context"></param> public override unsafe void WriteAsync(IntPtr sourceAddress, int segmentId, ulong destinationAddress, uint numBytesToWrite, DeviceIOCompletionCallback callback, object context) { HandleCapacity(segmentId); 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)(destinationAddress & 0xFFFFFFFF)); ovNative->OffsetHigh = unchecked ((int)((destinationAddress >> 32) & 0xFFFFFFFF)); try { var logHandle = GetOrAddHandle(segmentId); Interlocked.Increment(ref numPending); bool _result = Native32.WriteFile(logHandle, sourceAddress, numBytesToWrite, out uint bytesWritten, ovNative); if (!_result) { int error = Marshal.GetLastWin32Error(); if (error != Native32.ERROR_IO_PENDING) { throw new IOException("Error writing to 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 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)); /* Invoking the Native method WriteFile provided by Kernel32.dll * library. Returns false, if request failed or accepted for async * operation. Returns true, if success synchronously. */ uint bytesWritten = default(uint); bool result = Native32.WriteFile(logHandle, sourceAddress, numBytesToWrite, out bytesWritten, 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 writing to log file: " + error); } } else { //executed synchronously, so process callback callback(0, bytesWritten, ovNative); } }