Beispiel #1
0
        /// <summary>
        /// Creates the pipeline for streaming the block to DataNodes
        /// </summary>
        /// <param name="blockInfo">Info of the block. Contains blockid, blocksize, and ipaddresses for pipeline creation</param>
        /// <param name="client">Client connection with first DataNode in pipe</param>
        /// <returns>Success of pipeline creation</returns>
        private bool GetPipeLineReady(ClientProto.BlockInfo blockInfo, out ClientProto.ClientProto.ClientProtoClient client)
        {
            ClientProto.StatusResponse readyResponse = new ClientProto.StatusResponse {
                Type = ClientProto.StatusResponse.Types.StatusType.Fail
            };
            try
            {
                Channel channel = new Channel(blockInfo.IpAddress[0] + ":" + "50051", ChannelCredentials.Insecure);

                blockInfo.IpAddress.RemoveAt(0);
                client = new ClientProto.ClientProto.ClientProtoClient(channel);

                readyResponse = client.GetReady(blockInfo);

                return(true);
            }
            catch (Exception e)
            {
#if Debug
                Console.WriteLine("Get ready failed: " + e.Message);
#endif
                client = null;
                return(false);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Creates the pipeline and writes to datanode
        /// </summary>
        /// <param name="blockInfo">Info of the block. Contains blockid, blocksize, and ipaddresses for pipeline creation</param>
        /// <param name="block">data of block</param>
        /// <returns>Returns true if streaming of data through newly created pipeline was successful</returns>
        private bool CreatePipelineAndWrite(ClientProto.BlockInfo blockInfo, byte[] block, long contentLength)
        {
            // Create pipeline from list
            if (GetPipeLineReady(blockInfo, out ClientProto.ClientProto.ClientProtoClient writeClient))
            {
                if (client != null)
                {
                    try
                    {
                        // Send block through pipeline
                        WriteBlock(writeClient, blockInfo, block, contentLength).Wait();
                        return(true);
                    }
                    catch (Exception e)
                    {
#if Debug
                        Console.WriteLine(e.Message);
#endif
                        return(false);
                    }
                }
            }
            return(false);
        }
Beispiel #3
0
        public ClientProto.BlockInfo AddBlockToFile(ClientProto.BlockInfo addedBlock)
        {
            try
            {
                string          path = addedBlock.FullPath;
                string          name = TraverseFileSystem(path);
                FileSystem.File file = CurrentDirectory.files[name];
                file.fileSize += addedBlock.BlockSize;

                // to be used to send back a write request to the client
                List <string> responseRequests = new List <string>();

                // stores blockID and adds it to the file.
                Guid id = Guid.Parse(addedBlock.BlockId.Value);
                if (!file.data.Contains(id))
                {
                    file.data.Add(id);
                }

                List <string> ipAddresses = DataNodeManager.Instance.GetDataNodesForReplication();

                // add it to the BlockID to DataNode Dictionary
                BlockID_To_ip.TryAdd(id, new List <string>());
                SaveFileDirectory();
                return(new ClientProto.BlockInfo {
                    BlockId = new ClientProto.UUID {
                        Value = id.ToString()
                    }, FullPath = path, BlockSize = addedBlock.BlockSize, IpAddress = { ipAddresses }
                });
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return(null);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Writes the block to the first DataNode
        /// </summary>
        /// <param name="client">Client Connection to the first DataNode</param>
        /// <param name="blockInfo">Info of the block. Contains blockid, blocksize, and ipaddresses for pipeline creation</param>
        /// <param name="block">Data of block</param>
        /// <returns>Task of the write or Exception on fail</returns>
        private async Task WriteBlock(ClientProto.ClientProto.ClientProtoClient client, ClientProto.BlockInfo blockInfo, byte[] block, long contentLength)
        {
            Metadata metaData = new Metadata {
                new Metadata.Entry("blockid", blockInfo.BlockId.Value),
                new Metadata.Entry("blocksize", blockInfo.BlockSize.ToString())
            };

            int totalBytesRead = 0;

            using (var call = client.WriteBlock(metaData))
            {
                bool dataNodeFailed = false;

                while (totalBytesRead < blockInfo.BlockSize)
                {
                    int length = Math.Min(Constants.ChunkSize, blockInfo.BlockSize - totalBytesRead);

                    // Make sure correct length of data is sent
                    byte[] chunk = new byte[length];

                    Buffer.BlockCopy(block, totalBytesRead, chunk, 0, length);

                    totalBytesRead            += length;
                    TotalBytesWrittenFromFile += length;

                    try
                    {
                        await call.RequestStream.WriteAsync(new ClientProto.BlockData {
                            Data = Google.Protobuf.ByteString.CopyFrom(chunk)
                        });

                        // Casts are very necessary here!
                        Console.Write("\rWriting File {0}", (((double)TotalBytesWrittenFromFile / (double)contentLength)).ToString("0.00%"));
                    }
                    catch (Exception e)
                    {
                        dataNodeFailed = true;
                        totalBytesRead = blockInfo.BlockSize; // Stop reading
#if Debug
                        throw new Exception("Writing block failed", e);
#endif
                    }
                }

                ClientProto.StatusResponse resp = new ClientProto.StatusResponse {
                    Type = ClientProto.StatusResponse.Types.StatusType.Fail
                };
                if (!dataNodeFailed)
                {
                    await call.RequestStream.CompleteAsync();

                    resp = await call.ResponseAsync;
                }
                if (resp.Type == ClientProto.StatusResponse.Types.StatusType.Fail)
                {
                    throw new Exception("Writing block failed");
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Processes stream in order to read the file
        /// </summary>
        /// <param name="stream">Stream of the file</param>
        /// <param name="contentLength">Length of the file</param>
        private void ProcessStream(Stream stream, long contentLength)
        {
            // Read from response stream until entire file is read
            long totalBytesRead = 0;

            byte[] block = new byte[Constants.BlockSize];
            while (totalBytesRead < contentLength)
            {
                try
                {
                    int bytesRead = 0;

                    // Read until block size or until all the file has been read
                    while (bytesRead < Constants.BlockSize && totalBytesRead != contentLength)
                    {
                        int length = Math.Min(block.Length, Constants.BlockSize - bytesRead);
                        int n      = stream.Read(block, bytesRead, length);
                        bytesRead      += n;
                        totalBytesRead += n;
                    }

                    ClientProto.BlockInfo blockInfo = new ClientProto.BlockInfo
                    {
                        BlockId = new ClientProto.UUID {
                            Value = Guid.NewGuid().ToString()
                        },
                        FullPath  = filePath,
                        BlockSize = bytesRead
                    };

                    bool writeSuccess = false;
                    while (!writeSuccess)
                    {
                        // Keep asking NameNode for new DataNodes if all fail
                        // Get DataNode locations to store block
                        blockInfo = client.QueryBlockDestination(blockInfo);
                        if (blockInfo.IpAddress.Count() == 0)
                        {
                            Console.WriteLine("SUFS is unavailable");
                            Environment.Exit(1);
                        }
                        for (int i = 0; i < blockInfo.IpAddress.Count(); i++)
                        {
                            // Need to reassign because classes are passed by reference and we are removing nodes
                            ClientProto.BlockInfo info = new ClientProto.BlockInfo
                            {
                                BlockId   = blockInfo.BlockId,
                                BlockSize = blockInfo.BlockSize,
                                FullPath  = blockInfo.FullPath,
                            };
                            info.IpAddress.AddRange(blockInfo.IpAddress);

                            if (CreatePipelineAndWrite(info, block, contentLength))
                            {
                                writeSuccess = true;
                                break;
                            }
                            else
                            {
                                if (blockInfo.IpAddress.Count() <= 1)
                                {
                                    Console.WriteLine("SUFS is unavailable");
                                    Environment.Exit(1);
                                }
                                // Try a different datanode first.
                                // This has a chance because this flow only fails if the first datanode fails to connect or somehow they all fail.
                                var tempAddresses = blockInfo.IpAddress.Shift();
                                blockInfo.IpAddress.Clear();
                                blockInfo.IpAddress.AddRange(tempAddresses);
                            }
                        }
                    }
                }
                catch (RpcException e)
                {
                    // Stop reading
                    totalBytesRead = contentLength;
                    Console.WriteLine("Failed to write file: " + e.Message);
                }
                catch (Exception e)
                {
#if Debug
                    Console.WriteLine(e.Message);
#endif
                }
            }
        }
Beispiel #6
0
 public override Task <ClientProto.BlockInfo> QueryBlockDestination(ClientProto.BlockInfo blockInfo, ServerCallContext context)
 {
     return(Task.FromResult(Program.Database.AddBlockToFile(blockInfo)));
 }