Skip to content

Commit

Permalink
Moved NetAsyncDownloader to its own file.
Browse files Browse the repository at this point in the history
  • Loading branch information
pjf committed Oct 24, 2014
1 parent 7373fc1 commit f0bb21b
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 202 deletions.
1 change: 1 addition & 0 deletions CKAN.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<Compile Include="KSPManager.cs" />
<Compile Include="KSPPathUtils.cs" />
<Compile Include="KSPPathConstants.cs" />
<Compile Include="NetAsyncDownloader.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand Down
202 changes: 0 additions & 202 deletions Net.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,208 +9,6 @@ namespace CKAN
/// <summary>
/// Doing something with the network? Do it here.
/// </summary>
public delegate void NetAsyncProgressReport(int percent, int bytesPerSecond, long bytesLeft);

public delegate void NetAsyncCompleted(Uri[] urls, string[] filenames, Exception[] errors);

public struct NetAsyncDownloaderDownloadPart
{
public WebClient agent;
public long bytesDownloaded;
public long bytesLeft;
public int bytesPerSecond;
public Exception error;
public TransactionalFileWriter fileWriter;
public int lastProgressUpdateSize;
public DateTime lastProgressUpdateTime;
public string path;
public int percentComplete;
public Uri url;
}

public class NetAsyncDownloader
{
// private static readonly ILog log = LogManager.GetLogger(typeof (NetAsyncDownloader));

private readonly NetAsyncDownloaderDownloadPart[] downloads;
public NetAsyncCompleted onCompleted = null;
public NetAsyncProgressReport onProgressReport = null;
private int queuePointer;

private FilesystemTransaction transaction;
private bool downloadCanceled = false;

public NetAsyncDownloader(Uri[] urls, string[] filenames = null)
{
downloads = new NetAsyncDownloaderDownloadPart[urls.Length];

for (int i = 0; i < downloads.Length; i++)
{
downloads[i].url = urls[i];
if (filenames != null)
{
downloads[i].path = filenames[i];
}
else
{
downloads[i].path = null;
}
}
}

// starts the download and return the destination filename
public string[] StartDownload()
{
var filePaths = new string[downloads.Length];
transaction = new FilesystemTransaction(KSPManager.CurrentInstance.TempDir());

for (int i = 0; i < downloads.Length; i++)
{
User.WriteLine("Downloading \"{0}\"", downloads[i].url);

// Generate a temporary file if none is provided.
if (downloads[i].path == null)
{
downloads[i].path = Path.GetTempFileName();
}

filePaths[i] = downloads[i].path;

downloads[i].agent = new WebClient();
downloads[i].error = null;
downloads[i].percentComplete = 0;
downloads[i].lastProgressUpdateTime = DateTime.Now;
downloads[i].lastProgressUpdateSize = 0;
downloads[i].bytesPerSecond = 0;
downloads[i].bytesLeft = 0;

int index = i;
downloads[i].agent.DownloadProgressChanged +=
(sender, args) =>
FileProgressReport(index, args.ProgressPercentage, args.BytesReceived,
args.TotalBytesToReceive - args.BytesReceived);

downloads[i].agent.DownloadFileCompleted += (sender, args) => FileDownloadComplete(index, args.Error);

downloads[i].fileWriter = transaction.OpenFileWrite(downloads[i].path, false);
downloads[i].agent.DownloadFileAsync(downloads[i].url, downloads[i].fileWriter.TemporaryPath);
}

return filePaths;
}

public void CancelDownload()
{
foreach (var download in downloads)
{
download.agent.CancelAsync();
}

if (onCompleted != null)
{
onCompleted(null, null, null);
}

downloadCanceled = true;
}

private void FileProgressReport(int index, int percent, long bytesDownloaded, long bytesLeft)
{
if (downloadCanceled)
{
return;
}

NetAsyncDownloaderDownloadPart download = downloads[index];

download.percentComplete = percent;

DateTime now = DateTime.Now;
TimeSpan timeSpan = now - download.lastProgressUpdateTime;
if (timeSpan.Seconds >= 1.0)
{
long bytesChange = bytesDownloaded - download.lastProgressUpdateSize;
download.lastProgressUpdateSize = (int) bytesDownloaded;
download.lastProgressUpdateTime = now;
download.bytesPerSecond = (int) bytesChange/timeSpan.Seconds;
}

download.bytesLeft = bytesLeft;
download.bytesDownloaded = bytesDownloaded;
downloads[index] = download;

if (onProgressReport != null)
{
int totalPercentage = 0;
int totalBytesPerSecond = 0;
long totalBytesLeft = 0;
long totalBytesDownloaded = 0;

for (int i = 0; i < downloads.Length; i++)
{
totalBytesPerSecond += downloads[i].bytesPerSecond;
totalBytesLeft += downloads[i].bytesLeft;
totalBytesDownloaded += downloads[i].bytesDownloaded;
totalBytesLeft += downloads[i].bytesLeft;
}

totalPercentage = (int)((totalBytesDownloaded * 100) / (totalBytesLeft + totalBytesDownloaded + 1));

if (!downloadCanceled)
{
onProgressReport(totalPercentage, totalBytesPerSecond, totalBytesLeft);
}
}
}

private void FileDownloadComplete(int index, Exception error)
{
queuePointer++;
downloads[index].error = error;

if (queuePointer == downloads.Length)
{
// verify no errors before commit

bool err = false;
for (int i = 0; i < downloads.Length; i++)
{
if (downloads[i].error != null)
{
err = true;
}
}

if (!err)
{
transaction.Commit();
}

if (onCompleted != null)
{
var fileUrls = new Uri[downloads.Length];
var filePaths = new string[downloads.Length];
var errors = new Exception[downloads.Length];

for (int i = 0; i < downloads.Length; i++)
{
fileUrls[i] = downloads[i].url;
filePaths[i] = downloads[i].path;
errors[i] = downloads[i].error;
}

onCompleted(fileUrls, filePaths, errors);
}
}
}

public void WaitForAllDownloads()
{
while (queuePointer < downloads.Length)
{
}
}
}

public class Net
{
Expand Down
Loading

0 comments on commit f0bb21b

Please sign in to comment.