/// <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); }
/// <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); } }
/// <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); } }
/// <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 }); } }
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) { } }
/// <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 } }
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); } }