public override bool Equals(object obj) { if (base.Equals(obj)) { return(true); } FileBlockDownloadManager o = obj as FileBlockDownloadManager; if (o == null) { return(false); } return(o._blockNumber == this._blockNumber); }
private bool WriteBlock(FileBlockDownloadManager downloadedBlock) { int blockNumber = downloadedBlock.BlockNumber; lock (_blockAvailable) { if (_blockAvailable[blockNumber] == FileBlockState.Available) { return(true); } byte[] blockData = downloadedBlock.BlockData; byte[] actualHash = _metaData.BlockHash[blockNumber]; byte[] computedHash = _metaData.ComputeBlockHash(blockData); for (int i = 0; i < actualHash.Length; i++) { if (actualHash[i] != computedHash[i]) { return(false); } } lock (_fileStream) { _fileStream.Position = blockNumber * _metaData.BlockSize; _fileStream.Write(blockData, 0, blockData.Length); } _blockAvailable[blockNumber] = FileBlockState.Available; _availableBlocksCount++; } Interlocked.Add(ref _bytesDownloadedLastSecond, downloadedBlock.BlockData.Length); //add bytes downloaded for transfer speed calc return(true); }
private void OnBlockDownloaded(FileBlockDownloadManager downloadedBlock) { lock (_downloadingBlocks) { if (_downloadingBlocks.Remove(downloadedBlock)) { if (WriteBlock(downloadedBlock)) { //block downloaded //Debug.Write("SharedFile.BlockDownloaded", "block: " + downloadedBlock.BlockNumber); if (BlockDownloaded != null) { RaiseEventBlockDownloaded(); } } else { //block download fail/corrupt; add block again in pending list lock (_pendingBlocks) { _pendingBlocks.Add(downloadedBlock.BlockNumber); } } //start new block download FileBlockDownloadManager newDownload = GetRandomDownloadBlock(); if (newDownload != null) { _downloadingBlocks.Add(newDownload); } if (_downloadingBlocks.Count == 0) { //download COMPLETED! //set variables _isComplete = true; _state = SharedFileState.Sharing; _availableBlocksCount = _blockAvailable.Length; //stop download monitor _downloadMonitor.Dispose(); _downloadMonitor = null; //rename and open file again in read shared mode string filePath = _fileStream.Name; _fileStream.Close(); File.SetLastWriteTimeUtc(filePath, _metaData.LastModified); string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); File.Move(filePath, newFilePath); _fileStream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); //remove seeders lock (_seeders) { _seeders.Clear(); } //announce advertisement for the complete file to all chats available with same file SendFileAdvertisement(); //notify event to UI //Debug.Write("SharedFile.BlockDownloaded", "COMPLETED!"); if (FileDownloaded != null) { RaiseEventFileDownloaded(); } } } } }
private void DownloadMonitorAsync(object state) { try { if (_state == SharedFileState.Paused) { _downloadMonitor = null; return; } lock (_downloadingBlocks) { bool addAnotherBlockForDownload = false; List <FileBlockDownloadManager> inactiveDownloadBlocks = new List <FileBlockDownloadManager>(); foreach (FileBlockDownloadManager download in _downloadingBlocks) { if ((DateTime.UtcNow - download.LastResponse).TotalSeconds > DOWNLOAD_INACTIVE_INTERVAL_SECONDS) { //Debug.Write("SharedFile.DownloadMonitorAsync", "InactiveBlock: " + download.BlockNumber); if (!download.IsDownloadPeerSet()) { //add to inactive list inactiveDownloadBlocks.Add(download); //add another random block if available to mitigate case when all current blocks peer are not responding addAnotherBlockForDownload = true; } //remove current peer as he is not responding and set last response time download.SetDownloadPeer(null); //re-announce block requirement AnnounceBlockWanted(download.BlockNumber); } } //add another random block if available to mitigate case when all current blocks peer are not responding //this will allow downloading other data blocks from other peers when current block peers not responding if (addAnotherBlockForDownload) { FileBlockDownloadManager download = GetRandomDownloadBlock(); if (download != null) { _downloadingBlocks.Add(download); } } //remove extra inactive blocks to maintain total x 2 numbe of blocks //this will prevent memory getting filled with large number of inactive blocks if (_downloadingBlocks.Count > TOTAL_DOWNLOAD_BLOCKS * 2) { foreach (FileBlockDownloadManager downloadBlock in inactiveDownloadBlocks) { _downloadingBlocks.Remove(downloadBlock); if (_downloadingBlocks.Count <= TOTAL_DOWNLOAD_BLOCKS * 2) { break; } } } } } catch (ThreadAbortException) { _downloadMonitor = null; } catch (Exception ex) { Debug.Write("SharedFile.DownloadMonitorAsync", ex); } finally { if (_downloadMonitor != null) { _downloadMonitor.Change(DOWNLOAD_MONITOR_INTERVAL, Timeout.Infinite); } } }
private void StartDownload() { if (_state != SharedFileState.Downloading) { _state = SharedFileState.Downloading; //get file if (_fileStream == null) { //find file name string filePath = Path.Combine(_profile.DownloadFolder, _metaData.FileName); int nameCount = 0; while (File.Exists(filePath)) { if (nameCount > 10000) { throw new BitChatException("Cannot download file as local file name not available."); } nameCount++; filePath = Path.Combine(_profile.DownloadFolder, Path.GetFileNameWithoutExtension(_metaData.FileName) + " [" + nameCount + "]" + Path.GetExtension(_metaData.FileName)); } //create file _fileStream = new FileStream(filePath + ".downloading", FileMode.Create, FileAccess.ReadWrite); //pre-allocate file _fileStream.SetLength(_metaData.FileSize); //init block available _blockAvailable = new FileBlockState[_blockAvailable.Length]; _availableBlocksCount = 0; } //list all pending blocks if (_pendingBlocks == null) { _pendingBlocks = new List <int>(_blockAvailable.Length); _rndPendingBlock = new Random(DateTime.UtcNow.Second); for (int i = 0; i < _blockAvailable.Length; i++) { if (_blockAvailable[i] != FileBlockState.Available) { _pendingBlocks.Add(i); } } } //announce file sharing participation in chats SendFileShareParticipate(); //start block download _downloadingBlocks = new List <FileBlockDownloadManager>(TOTAL_DOWNLOAD_BLOCKS); lock (_downloadingBlocks) { for (int i = 0; i < TOTAL_DOWNLOAD_BLOCKS; i++) { FileBlockDownloadManager download = GetRandomDownloadBlock(); if (download == null) { break; } _downloadingBlocks.Add(download); } } //start file transfer speed calculator _fileTransferSpeedCalculator = new Timer(FileTransferSpeedCalculatorAsync, null, 1000, 1000); //start download monitor _downloadMonitor = new Timer(DownloadMonitorAsync, null, DOWNLOAD_MONITOR_INTERVAL, Timeout.Infinite); if (FileDownloadStarted != null) { RaiseEventFileDownloadStarted(); } } }
private void OnBlockDownloaded(FileBlockDownloadManager downloadedBlock) { lock (_downloadingBlocks) { if (_downloadingBlocks.Remove(downloadedBlock)) { if (WriteBlock(downloadedBlock)) { //block downloaded //Debug.Write("SharedFile.BlockDownloaded", "block: " + downloadedBlock.BlockNumber); if (BlockDownloaded != null) RaiseEventBlockDownloaded(); } else { //block download fail/corrupt; add block again in pending list lock (_pendingBlocks) { _pendingBlocks.Add(downloadedBlock.BlockNumber); } } //start new block download FileBlockDownloadManager newDownload = GetRandomDownloadBlock(); if (newDownload != null) _downloadingBlocks.Add(newDownload); if (_downloadingBlocks.Count == 0) { //download COMPLETED! //set variables _isComplete = true; _state = SharedFileState.Sharing; _availableBlocksCount = _blockAvailable.Length; //stop download monitor _downloadMonitor.Dispose(); _downloadMonitor = null; //rename and open file again in read shared mode string filePath = _fileStream.Name; _fileStream.Close(); File.SetLastWriteTimeUtc(filePath, _metaData.LastModified); string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)); File.Move(filePath, newFilePath); _fileStream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); //remove seeders lock (_seeders) { _seeders.Clear(); } //announce advertisement for the complete file to all chats available with same file SendFileAdvertisement(); //notify event to UI //Debug.Write("SharedFile.BlockDownloaded", "COMPLETED!"); if (FileDownloaded != null) RaiseEventFileDownloaded(); } } } }
private bool WriteBlock(FileBlockDownloadManager downloadedBlock) { int blockNumber = downloadedBlock.BlockNumber; lock (_blockAvailable) { if (_blockAvailable[blockNumber] == FileBlockState.Available) return true; byte[] blockData = downloadedBlock.BlockData; byte[] actualHash = _metaData.BlockHash[blockNumber]; byte[] computedHash = _metaData.ComputeBlockHash(blockData); for (int i = 0; i < actualHash.Length; i++) { if (actualHash[i] != computedHash[i]) return false; } lock (_fileStream) { _fileStream.Position = blockNumber * _metaData.BlockSize; _fileStream.Write(blockData, 0, blockData.Length); } _blockAvailable[blockNumber] = FileBlockState.Available; _availableBlocksCount++; } Interlocked.Add(ref _bytesDownloadedLastSecond, downloadedBlock.BlockData.Length); //add bytes downloaded for transfer speed calc return true; }