/// <summary>
        /// Downloads the torrent of the piece and write it to
        /// </summary>
        /// <param name="nameSpace">The name space.</param>
        /// <param name="name">The name.</param>
        /// <param name="wholeTorrent">The whole torrent.</param>
        /// <param name="pieceIndex">Index of the piece.</param>
        byte[] DownloadPieceTorrent(string nameSpace, string name, Torrent wholeTorrent,
                                    int pieceIndex)
        {
            var wholeTorrentDhtKeyStr = ServiceUtil.GetDictKeyString(nameSpace, name);
            var pieceKeyStr           = MakePieceTorrentKey(wholeTorrentDhtKeyStr, pieceIndex);
            var torrentFilePath       = _bittorrentCache.GetTorrentFilePath(nameSpace, name);

            byte[] pieceTorrentBytes;
            bool   succ = _torrentHelper.TryReadOrDownloadTorrent(
                nameSpace, name, _dhtProxy, out pieceTorrentBytes);

            if (succ)
            {
                // Somebody else already requested this piece.
                return(pieceTorrentBytes);
            }
            else
            {
                // We need to request the seeder to make a new piece.
                IEnumerable <PeerEntry> peers = _dhtProxy.GetPeers(wholeTorrent.InfoHash.ToArray());
                bool foundCompletePeer        = false;

                // The list most likely has only one entry.
                var trackerIPs = new List <string>();
                foreach (var tiers in wholeTorrent.AnnounceUrls)
                {
                    foreach (var trackerUrl in tiers)
                    {
                        // Given that we don't use domain names for hosts.
                        trackerIPs.Add(new Uri(trackerUrl).Host);
                    }
                }

                // Completed -> Downloader has the whole data.
                // PeerIP == Tracker -> Original Seeder(s).
                var peerIPs = (from peer in peers
                               where (peer.PeerState == TorrentEvent.Completed ||
                                      trackerIPs.Contains(peer.PeerIP))
                               select peer.PeerIP).Distinct();
                Logger.WriteLineIf(LogLevel.Verbose, _log_props, string.Format(
                                       "{0} peers to try for piece info.", peerIPs.Count()));

                foreach (var peerIP in peerIPs)
                {
                    foundCompletePeer = true;
                    // The first complete peer should be able to serve the piece we want.
                    bool succPieceInfo = TryDownloadPieceTorrentFromPeer(nameSpace,
                                                                         name, pieceIndex, peerIP, _pieceInfoServerPort,
                                                                         out pieceTorrentBytes);
                    if (succPieceInfo)
                    {
                        Logger.WriteLineIf(LogLevel.Verbose, _log_props,
                                           string.Format("Piece info downloaded from {0}", peerIP));
                        return(pieceTorrentBytes);
                    }
                    else
                    {
                        // Try the next completePeer
                        continue;
                    }
                }

                if (!foundCompletePeer)
                {
                    throw new DictionaryKeyNotFoundException("No peer is complete.");
                }
                else if (pieceTorrentBytes == null)
                {
                    throw new DictionaryKeyNotFoundException(
                              "No complete peer(s) can return the piece Info");
                }
                else
                {
                    // This shouldn't happen
                    return(pieceTorrentBytes);
                }
            }
        }