Beispiel #1
0
        /// <summary>
        /// Server side handler of the WriteDataBlock RPC. DataNode writes block to a file and then returns success status of write.
        /// </summary>
        /// <param name="requestStream">Stream of bytes</param>
        /// <param name="context">Context of call. Contains metadata containing blockid and list of addresses</param>
        /// <returns>Status of task</returns>
        public override async Task <ClientProto.StatusResponse> WriteBlock(Grpc.Core.IAsyncStreamReader <ClientProto.BlockData> requestStream, ServerCallContext context)
        {
            List <Metadata.Entry> metaData = context.RequestHeaders.ToList();

            // Get blockID
            Guid blockId   = Util.GetBlockID(metaData);
            int  blockSize = Util.GetBlockSize(metaData);

            string filePath = BlockStorage.Instance.CreateFile(blockId);

            Channel channel = ConnectionManager.Instance.GetChannel(blockId);

            ClientProto.StatusResponse response = new ClientProto.StatusResponse {
                Type = ClientProto.StatusResponse.Types.StatusType.Success
            };
            // No channel found means last datanode in pipe
            if (channel != null)
            {
                response = await WriteAndForwardBlock(requestStream, context, channel, filePath, blockId, blockSize);
            }
            else // Just write to file
            {
                response = await WriteBlock(requestStream, filePath, blockId, blockSize);
            }

            if (response.Type == ClientProto.StatusResponse.Types.StatusType.Success)
            {
                Console.WriteLine("Done writing block: " + blockId.ToString());
                // Send block report to NameNode
                var client = new DataNodeProto.DataNodeProto.DataNodeProtoClient(ConnectionManager.Instance.NameNodeConnection);
                BlockReport.SendSingleBlockReport(client);
            }

            return(response);
        }
Beispiel #2
0
        /// <summary>
        /// Sends block report in loop
        /// </summary>
        /// <param name="client">Datanode grpc client</param>
        public static async Task SendBlockReport(DataNodeProto.DataNodeProto.DataNodeProtoClient client)
        {
            while (true)
            {
                SendSingleBlockReport(client);

                await Task.Delay(Constants.BlockReportInterval);
            }
        }
Beispiel #3
0
 /// <summary>
 /// Sends a single block report
 /// </summary>
 /// <param name="client">Connection to NameNode</param>
 public static void SendSingleBlockReport(DataNodeProto.DataNodeProto.DataNodeProtoClient client)
 {
     try
     {
         DataNodeProto.BlockReportRequest blockReport = CreateBlockReport();
         DataNodeProto.StatusResponse     response    = client.SendBlockReport(blockReport);
     }
     catch (RpcException e)
     {
         Console.WriteLine("Blockreport failed: " + e.Message);
     }
 }
Beispiel #4
0
        /// <summary>
        /// Server side handler of the WriteDataBlock RPC. DataNode writes block to a file and then returns success status of write.
        /// </summary>
        /// <param name="requestStream">Data of block</param>
        /// <param name="context">Call Context</param>
        /// <returns>Status of task</returns>
        public override async Task <DataNodeProto.StatusResponse> WriteDataBlock(Grpc.Core.IAsyncStreamReader <DataNodeProto.BlockData> requestStream, ServerCallContext context)
        {
            List <Metadata.Entry> metaData = context.RequestHeaders.ToList();
            Guid blockId   = Util.GetBlockID(metaData);
            int  blockSize = Util.GetBlockSize(metaData);

            string filePath = BlockStorage.Instance.CreateFile(blockId);

            bool writeSuccess = true;

            try
            {
                // Write block to file system
                using (var writerStream = new FileStream(filePath, FileMode.Append, FileAccess.Write))
                {
                    while (await requestStream.MoveNext())
                    {
                        try
                        {
                            var bytes = requestStream.Current.Data.ToByteArray();
                            writerStream.Write(bytes, 0, bytes.Length);
                        }
                        catch
                        {
                            writeSuccess = false;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Writing block that was forwarded failed: " + e.Message);
            }

            if (BlockStorage.Instance.ValidateBlock(blockId, filePath, blockSize) && writeSuccess)
            {
                // Send block report to NameNode
                var client = new DataNodeProto.DataNodeProto.DataNodeProtoClient(ConnectionManager.Instance.NameNodeConnection);
                BlockReport.SendSingleBlockReport(client);
                return(new DataNodeProto.StatusResponse {
                    Type = DataNodeProto.StatusResponse.Types.StatusType.Success
                });
            }
            else
            {
                return(new DataNodeProto.StatusResponse {
                    Type = DataNodeProto.StatusResponse.Types.StatusType.Fail
                });
            }
        }
Beispiel #5
0
        static void Main(string[] args)
        {
            Console.WriteLine("Initializing DataNode");
            string nameNodeIp = args[0];

            int port = Convert.ToInt32(args[1]);

            // Use ec2 instance manager to get the private ip address of this data node
            EC2InstanceManager.InstanceManager instanceManager = EC2InstanceManager.InstanceManager.Instance;
            ipAddress = instanceManager.GetPrivateIpAddress();

#if DEBUG
            if (ipAddress == null)
            {
                ipAddress = "localhost";
            }
#endif

            Server server = new Server
            {
                Services = { DataNodeProto.DataNodeProto.BindService(new DataNodeHandler()),
                             ClientProto.ClientProto.BindService(new ClientHandler()) },
                //Ports = { new ServerPort(ipAddress, Constants.Port, ServerCredentials.Insecure) }
                Ports = { new ServerPort(ipAddress, port, ServerCredentials.Insecure) }
            };

            Console.WriteLine("Done initializing");

            server.Start();

            Console.WriteLine("Trying to connect to: " + nameNodeIp);
            Channel channel = new Channel(nameNodeIp + ":" + Constants.Port, ChannelCredentials.Insecure);
            ConnectionManager.Instance.NameNodeConnection = channel;
            var client = new DataNodeProto.DataNodeProto.DataNodeProtoClient(channel);

            // Send initial heartbeat to initialize datanode in namenode
            var response = client.SendHeartBeat(HeartBeat.CreateHeartBeatRequest(), new CallOptions().WithWaitForReady(true));
            Console.WriteLine("Successfully connected to namenode");

            // Initialize blockstorage
            BlockStorage mBlockStorage = BlockStorage.Instance;

            Task heartBeatTask   = HeartBeat.SendHeartBeat(client);
            Task blockReportTask = BlockReport.SendBlockReport(client);
            while (true)
            {
            }
        }
Beispiel #6
0
        /// <summary>
        /// Send blockreport
        /// </summary>
        /// <param name="client">Datanode grpc client</param>
        public static async Task SendHeartBeat(DataNodeProto.DataNodeProto.DataNodeProtoClient client)
        {
            while (true)
            {
                DataNodeProto.HeartBeatRequest heartBeatRequest = CreateHeartBeatRequest();

                try
                {
                    DataNodeProto.HeartBeatResponse response         = client.SendHeartBeat(heartBeatRequest);
                    DataNodeProto.BlockCommand      nameNodeCommands = response.Commands;
                    switch (nameNodeCommands.Action)
                    {
                    case DataNodeProto.BlockCommand.Types.Action.Transfer:
                        foreach (var block in nameNodeCommands.DataBlock.ToList())
                        {
                            // Get block data
                            byte[] blockData = BlockStorage.Instance.ReadBlock(Guid.Parse(block.BlockId.Value));

                            if (blockData != null)
                            {
                                Metadata metaData = new Metadata {
                                    new Metadata.Entry("blockid", block.BlockId.Value),
                                    new Metadata.Entry("blocksize", blockData.Length.ToString())
                                };

                                // Send data to each block
                                foreach (var dataNode in block.DataNodes)
                                {
                                    Task task = ForwardBlock(dataNode, blockData, metaData);
                                }
                            }
                        }
                        break;

                    case DataNodeProto.BlockCommand.Types.Action.Delete:
                        InvalidateBlocks(nameNodeCommands.BlockList);
                        break;
                    }
                }
                catch (RpcException e)
                {
                    Console.WriteLine("HeartBeat failed: " + e.Message);
                }
                await Task.Delay(Constants.HeartBeatInterval); // This is an HDFS default
            }
        }
Beispiel #7
0
        public static async Task ForwardBlock(DataNodeProto.DataNode dataNode, byte[] blockData, Metadata metadata)
        {
            try
            {
                Console.WriteLine("Fowarding block to " + dataNode.IpAddress);
                Channel channel    = new Channel(dataNode.IpAddress + ":" + Constants.Port, ChannelCredentials.Insecure);
                var     nodeClient = new DataNodeProto.DataNodeProto.DataNodeProtoClient(channel);

                using (var call = nodeClient.WriteDataBlock(metadata))
                {
                    int remaining = blockData.Length;

                    while (remaining > 0)
                    {
                        var    copyLength   = Math.Min(Constants.StreamChunkSize, remaining);
                        byte[] streamBuffer = new byte[copyLength];

                        Buffer.BlockCopy(
                            blockData,
                            blockData.Length - remaining,
                            streamBuffer, 0,
                            copyLength);

                        await call.RequestStream.WriteAsync(new DataNodeProto.BlockData {
                            Data = Google.Protobuf.ByteString.CopyFrom(streamBuffer)
                        });

                        remaining -= copyLength;
                    }

                    await call.RequestStream.CompleteAsync();

                    var resp = await call.ResponseAsync;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Problem forwarding block to node," + e);
            }
        }