// Initializes the LU registration details from the incoming payload. private void InitLURegistration() { byte[] arrPayload = new byte[SizePayloadBuffer]; int iTotalBytesRead = SFBlockStoreCommunicationListener.FetchDataFromTransport(ClientStream, PipeServer, arrPayload, (int)SizePayloadBuffer); // Did we get a buffer of expected size? if (iTotalBytesRead != SizePayloadBuffer) { throw new InvalidOperationException(String.Format("SFBlockstoreService::InitLURegistration: Malformed request of size {0} encountered; expected size is {1}", iTotalBytesRead, SizePayloadBuffer)); } // Create a BinaryReader around the incoming array to parse the data out of it MemoryStream msPayload = new MemoryStream(arrPayload); BinaryReader reader = new BinaryReader(msPayload); // Read the LU registration information LengthLUID = reader.ReadUInt32(); // Read the Disk size DiskSize = reader.ReadUInt32(); // Read the Disk size unit DiskSizeUnit = reader.ReadUInt32(); // Read the Mount status Mounted = reader.ReadUInt32(); // Read the LUID byte[] arrLUID = reader.ReadBytes((int)LengthLUID); unsafe { fixed(byte *pLUID = arrLUID) { IntPtr ptrLUID = new IntPtr(pLUID); LUID = Marshal.PtrToStringUni(ptrLUID); } } reader.Close(); }
private void FetchRegisteredLUList(IBSManager bsManager, CancellationToken cancellationToken) { ValidateArgs(false); // This request comes with a blockSizeManagementRequest sized empty payload buffer. Fetch that from the stream // to get it out of the way so that we have completed reading the header+(empty)payload. uint LengthBuffer = SizePayloadBuffer; byte[] arrPayload = new byte[LengthBuffer]; int bytesToRead = (int)LengthBuffer; int iTotalBytesFetched = SFBlockStoreCommunicationListener.FetchDataFromTransport(ClientStream, PipeServer, arrPayload, bytesToRead); // Did we get a buffer of expected size? if (iTotalBytesFetched != bytesToRead) { throw new InvalidOperationException(String.Format("SFBlockstoreService::FetchRegisteredLUList: Malformed request of size {0} encountered; expected size is {1}", iTotalBytesFetched, bytesToRead)); } Console.WriteLine("SFBlockstoreService::FetchRegisteredLUList: Fetching registered LUs"); // Prepare to write the outgoing data MemoryStream msPayload = new MemoryStream((int)GatewayPayloadConst.blockSizeManagementRequest); BinaryWriter writer = new BinaryWriter(msPayload); // Registrated LU List format is as follows: // // <Number of Entries> // LengthLUID <-- Entry starts here // DiskSize // DiskSizeUnit // Mounted // LUID <-- Entry ends here // // ...repeat Task <ArrayList> listLU = bsManager.FetchLURegistrations(DeviceID, cancellationToken); ArrayList listRegisteredLU = listLU.Result; int iLURegistrations = (listRegisteredLU != null)?listRegisteredLU.Count:0; if (iLURegistrations > 0) { // Write the number of registration entries if (iLURegistrations > GatewayPayloadConst.maxLURegistrations) { Console.WriteLine("SFBlockstoreService::FetchRegisteredLUList: Trimming LU registration list from {0} to {1}", iLURegistrations, GatewayPayloadConst.maxLURegistrations); iLURegistrations = GatewayPayloadConst.maxLURegistrations; } writer.Write(iLURegistrations); // Loop through each registration to compose the payload int iIndex = 0; foreach (string entry in listRegisteredLU) { if (iIndex < iLURegistrations) { // Split the entry into LUID and Registration info string[] arrData = entry.Split(new string[] { "::" }, StringSplitOptions.None); // Add the NULL to the string when sending across the wire. string szLUID = arrData[0] + "\0"; // Convert the LUID to byte array byte[] arrLUID = System.Text.Encoding.Unicode.GetBytes(szLUID); // Write the length of LUID in bytes (and not characters) writer.Write(arrLUID.Length); // Get the Disksize and Size unit string[] arrDiskSizeData = arrData[1].Split(new char[] { '_' }); // Write the DiskSize writer.Write(Int32.Parse(arrDiskSizeData[0])); // Write the DiskSize Unit writer.Write(Int32.Parse(arrDiskSizeData[1])); // Write the Mounted status writer.Write(Int32.Parse(arrDiskSizeData[2])); // Finally, write the LUID writer.Write(arrLUID); iIndex++; } else { break; } } Console.WriteLine("SFBlockstoreService::FetchRegisteredLUList: Fetched {0} LU registrations", iLURegistrations); } else { iLURegistrations = 0; writer.Write(iLURegistrations); Console.WriteLine("SFBlockstoreService::FetchRegisteredLUList: No LU registrations found."); } // Set the payload and its actual length so that // the right amount of data is copied from the payload // we send (including nothing when the payload is empty). PayloadData = msPayload.GetBuffer(); SizePayloadBuffer = (uint)msPayload.ToArray().Length; Console.WriteLine("SFBlockstoreService::FetchRegisteredLUList: Returned payload size is {0}.", SizePayloadBuffer); writer.Close(); // Set mode to indicate success Mode = BlockMode.OperationCompleted; }
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; } }
public static GatewayPayload ParseHeader(byte[] arrPayload, NamedPipeServerStream pipeServer, SFBlockStoreCommunicationListener commListener) { GatewayPayload payload = new GatewayPayload(); payload.PipeServer = pipeServer; payload.ClientStream = null; payload.CommunicationListener = commListener; InitHeader(arrPayload, ref payload); return(payload); }