private void WriteBlocksToService(IBSManager bsManager) { ValidateArgs(true); ulong OffsetToWriteFrom = OffsetToRW; uint LengthBuffer = SizePayloadBuffer; ulong endOffset = OffsetToWriteFrom + LengthBuffer; bool fWriteSuccessful = true; ulong bytesToWrite = 0; ulong bytesWritten = 0; uint iCopyFromIndex = 0; bool fUseDMA = UseDMA; Console.WriteLine("SFBlockstoreService::WriteBlocksToService: Writing blocks device, {0}, at offset {1} for length {2}{3}", DeviceID, OffsetToRW, LengthBuffer, UseDMA ? " [DMA]" : String.Empty); byte[] arrPayload = new byte[LengthBuffer]; if (!fUseDMA) { // Fetch the data from the network in a single go and loop in block aligned size to write to the service. int iTotalBytesFetched = SFBlockStoreCommunicationListener.FetchDataFromTransport(ClientStream, PipeServer, arrPayload, arrPayload.Length); if (iTotalBytesFetched != arrPayload.Length) { throw new InvalidOperationException(String.Format("SFBlockstoreService::WriteBlocksToService: Malformed write-payload of size {0} encountered; expected size is {1}", iTotalBytesFetched, arrPayload.Length)); } } else { // Get the data from the kernel driver to write to the store. uint errorDMA = 0; // If we are going to use DMA, then get the reference to the SRB's DataBuffer unsafe { fixed(byte *pBuffer = arrPayload) { fWriteSuccessful = GetPayloadFromSRB(SRBAddress, pBuffer, LengthBuffer, &errorDMA); } } if (!fWriteSuccessful) { Console.WriteLine("SFBlockstoreService::WriteBlocksToService: Failed to read blocks from memory for SRB {3:X} for device, {0}, at offset {1} for length {2} due to error {4}", DeviceID, OffsetToRW, LengthBuffer, SRBAddress.ToUInt64(), errorDMA); } } if (fWriteSuccessful) { try { List <Task> listTasks = new List <Task>(); while (OffsetToWriteFrom < endOffset) { // How many bytes do we need to process from the current offset to end of the corresponding block? bytesToWrite = GatewayPayloadConst.blockSizeDisk - (OffsetToWriteFrom % GatewayPayloadConst.blockSizeDisk); if ((bytesToWrite + OffsetToWriteFrom) >= endOffset) { // We cannot go past the intended length, so adjust the length accordingly. bytesToWrite = endOffset - OffsetToWriteFrom; } Task taskWriteBlock = WriteBlockUnderTransaction(bsManager, OffsetToWriteFrom, bytesToWrite, iCopyFromIndex, arrPayload); listTasks.Add(taskWriteBlock); // Update the counters OffsetToWriteFrom += bytesToWrite; bytesWritten += bytesToWrite; iCopyFromIndex += (uint)bytesToWrite; } // Wait for all tasks to complete Task.WaitAll(listTasks.ToArray()); } catch (Exception ex) { fWriteSuccessful = false; Console.WriteLine("SFBlockstoreService::WriteBlocksToService: Failed to write blocks to device, {0}, at offset {1} for length {2} due to exception: {3} - {4}", DeviceID, OffsetToRW, LengthBuffer, ex.GetType(), ex.Message); } // Ensure we processed the expected length of data if (bytesWritten != LengthBuffer) { Console.WriteLine("SFBlockstoreService::WriteBlocksToService: Incomplete block write for device, {0}, at offset {1} for length {2}. Expected: {3}, Read: {4}", DeviceID, OffsetToRW, LengthBuffer, LengthBuffer, bytesWritten); fWriteSuccessful = false; } } // Reset the payload details before sending a response. SizePayloadBuffer = 0; PayloadData = null; if (fWriteSuccessful) { Console.WriteLine("SFBlockstoreService::WriteBlocksToService: Blocks successfully written to device, {0}, at offset {1} for length {2}", DeviceID, OffsetToRW, LengthBuffer); Mode = BlockMode.OperationCompleted; } else { Console.WriteLine("SFBlockstoreService::WriteBlocksToService: Failed to write blocks to device, {0}, at offset {1} for length {2}", DeviceID, OffsetToRW, LengthBuffer); Mode = BlockMode.OperationFailed; } }
internal void SendResponse() { // Create a new memory stream which will be wrapped up by BinaryWrite to construct the payload byte array. // The initial size of the stream is the same as the maximum payload buffer size as that is the size // in which the client (the driver) reads (the response) data from the service as well. int sizeResponseStream = GatewayPayloadConst.payloadHeaderSize + (int)SizePayloadBuffer; MemoryStream msPayload = new MemoryStream(sizeResponseStream); BinaryWriter writer = new BinaryWriter(msPayload); uint padding = 0xDEADBEEF; // // Write the header // writer.Write((uint)Mode); // Write the padding writer.Write(padding); writer.Write(OffsetToRW); writer.Write(SizePayloadBuffer); // Explicitly append the terminating null since GetBytes will not include it in the byte array returned. byte[] arrDeviceID = System.Text.Encoding.Unicode.GetBytes(DeviceID + "\0"); LengthDeviceID = (uint)arrDeviceID.Length; writer.Write(LengthDeviceID); writer.Write(SRBAddress.ToUInt64()); writer.Write(arrDeviceID); // Finally, write the EndOfPayloadMarker writer.Write(GatewayPayloadConst.EndOfPayloadMarker); // // Write the payload if one was expected to be sent // if ((SizePayloadBuffer > 0) && (PayloadData != null)) { // Move the writer to be after the header msPayload.Seek(GatewayPayloadConst.payloadHeaderSize, SeekOrigin.Begin); // Console.WriteLine("SFBlockstoreService::SendResponse: Writer is at position {0} to write the payload of length {1}", msPayload.Position, SizePayloadBuffer); // And then write the payload writer.Write(PayloadData); } // Get the entire buffer as opposed to getting only the used bytes (which is what ToArray returns). byte[] arrPayload = msPayload.GetBuffer(); writer.Close(); // Send away the response if (ClientStream != null) { //Use sync call because on return caller might tear down the socket. //ClientStream.WriteAsync(arrPayload, 0, arrPayload.Length); ClientStream.Write(arrPayload, 0, arrPayload.Length); } else { SendResponseOverNamedPipe(arrPayload); } }
private void ReadBlocksFromService(IBSManager bsManager) { ValidateArgs(true); uint LengthBuffer = SizePayloadBuffer; bool fReadSuccessful = true; bool fUseDMA = UseDMA; Console.WriteLine("SFBlockstoreService::ReadBlocksFromService: Reading blocks from device, {0}, at offset {1} for length {2}{3}", DeviceID, OffsetToRW, LengthBuffer, UseDMA?" [DMA]":String.Empty); // Allocate an array that will be able to contain the block data we have to read byte[] arrPayload = new byte[LengthBuffer]; uint iCopyToIndex = 0; ulong OffsetToReadFrom = OffsetToRW; ulong endOffset = OffsetToReadFrom + LengthBuffer; ulong bytesToRead = 0; try { List <Task> listTasks = new List <Task>(); while (OffsetToReadFrom < endOffset) { // How many bytes do we need to process from the current offset to end of the corresponding block? bytesToRead = GatewayPayloadConst.blockSizeDisk - (OffsetToReadFrom % GatewayPayloadConst.blockSizeDisk); if ((bytesToRead + OffsetToReadFrom) >= endOffset) { // We cannot go past the intended length, so adjust the length accordingly. bytesToRead = endOffset - OffsetToReadFrom; } Task readBlock = ReadBlockUnderTransaction(bsManager, arrPayload, iCopyToIndex, OffsetToReadFrom, bytesToRead); listTasks.Add(readBlock); // Move to the next offset OffsetToReadFrom += bytesToRead; iCopyToIndex += (uint)bytesToRead; } // Wait for all tasks to complete Task.WaitAll(listTasks.ToArray()); // Ensure we processed the expected length of data if (iCopyToIndex != LengthBuffer) { Console.WriteLine("SFBlockstoreService::ReadBlocksFromService: Incomplete blocks read for device, {0}, at offset {1} for length {2}. Expected: {3}, Read: {4}", DeviceID, OffsetToRW, LengthBuffer, LengthBuffer, iCopyToIndex); fReadSuccessful = false; } } catch (Exception ex) { fReadSuccessful = false; Console.WriteLine("SFBlockstoreService::ReadBlocksFromService: Failed to read blocks for device, {0}, at offset {1} for length {2} due to exception: {3} - {4}", DeviceID, OffsetToRW, LengthBuffer, ex.GetType(), ex.Message); } // Set the return payload buffer for the client to complete its receive request. if (!fUseDMA) { // When not using DMA, setup the array payload to be returned PayloadData = arrPayload; } else { if (fReadSuccessful) { // Pass the data we got from the store to the kernel driver. uint errorDMA = 0; unsafe { // If we are going to use DMA, then get the reference to the SRB's DataBuffer fixed(byte *pBuffer = arrPayload) { fReadSuccessful = CopyPayloadToSRB(SRBAddress, pBuffer, LengthBuffer, &errorDMA); } } if (!fReadSuccessful) { Console.WriteLine("SFBlockstoreService::ReadBlocksFromService: Failed to read blocks into memory for SRB {3:X} for device, {0}, at offset {1} for length {2} due to error {4}", DeviceID, OffsetToRW, LengthBuffer, SRBAddress.ToUInt64(), errorDMA); } } // We are not sending any payload over the wire, so reset the reference for response. SizePayloadBuffer = 0; PayloadData = null; } if (fReadSuccessful) { Console.WriteLine("SFBlockstoreService::ReadBlocksFromService: Blocks successfully read for device, {0}, at offset {1} for length {2}", DeviceID, OffsetToRW, LengthBuffer); Mode = BlockMode.OperationCompleted; } else { Console.WriteLine("SFBlockstoreService::ReadBlocksFromService: Failed to read blocks for device, {0}, at offset {1} for length {2}", DeviceID, OffsetToRW, LengthBuffer); Mode = BlockMode.OperationFailed; } }