Exemplo n.º 1
0
        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;
            }
        }
Exemplo n.º 2
0
        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);
            }
        }
Exemplo n.º 3
0
        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;
            }
        }