mirror of https://github.com/winsw/winsw
Optimize Download
parent
33da176920
commit
ba328e3162
|
@ -8,6 +8,9 @@ using System.Runtime.InteropServices;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
#if VNEXT
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
#endif
|
||||||
using log4net;
|
using log4net;
|
||||||
using log4net.Appender;
|
using log4net.Appender;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
|
@ -199,23 +202,54 @@ namespace winsw
|
||||||
HandleFileCopies();
|
HandleFileCopies();
|
||||||
|
|
||||||
// handle downloads
|
// handle downloads
|
||||||
foreach (Download d in _descriptor.Downloads)
|
#if VNEXT
|
||||||
|
List<Download> downloads = _descriptor.Downloads;
|
||||||
|
Task[] tasks = new Task[downloads.Count];
|
||||||
|
for (int i = 0; i < downloads.Count; i++)
|
||||||
{
|
{
|
||||||
string downloadMsg = "Downloading: " + d.From + " to " + d.To + ". failOnError=" + d.FailOnError;
|
Download download = downloads[i];
|
||||||
LogEvent(downloadMsg);
|
string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}";
|
||||||
Log.Info(downloadMsg);
|
LogEvent(downloadMessage);
|
||||||
|
Log.Info(downloadMessage);
|
||||||
|
tasks[i] = download.PerformAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Task.WhenAll(tasks);
|
||||||
|
for (int i = 0; i < tasks.Length; i++)
|
||||||
|
{
|
||||||
|
if (tasks[i].IsFaulted)
|
||||||
|
{
|
||||||
|
Download download = downloads[i];
|
||||||
|
string errorMessage = $"Failed to download {download.From} to {download.To}";
|
||||||
|
AggregateException exception = tasks[i].Exception!;
|
||||||
|
LogEvent($"{errorMessage}. {exception.Message}");
|
||||||
|
Log.Error(errorMessage, exception);
|
||||||
|
|
||||||
|
// TODO: move this code into the download logic
|
||||||
|
if (download.FailOnError)
|
||||||
|
{
|
||||||
|
throw new IOException(errorMessage, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
foreach (Download download in _descriptor.Downloads)
|
||||||
|
{
|
||||||
|
string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}";
|
||||||
|
LogEvent(downloadMessage);
|
||||||
|
Log.Info(downloadMessage);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.Perform();
|
download.Perform();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMessage = "Failed to download " + d.From + " to " + d.To;
|
string errorMessage = $"Failed to download {download.From} to {download.To}";
|
||||||
LogEvent(errorMessage + ". " + e.Message);
|
LogEvent($"{errorMessage}. {e.Message}");
|
||||||
Log.Error(errorMessage, e);
|
Log.Error(errorMessage, e);
|
||||||
|
|
||||||
// TODO: move this code into the download logic
|
// TODO: move this code into the download logic
|
||||||
if (d.FailOnError)
|
if (download.FailOnError)
|
||||||
{
|
{
|
||||||
throw new IOException(errorMessage, e);
|
throw new IOException(errorMessage, e);
|
||||||
}
|
}
|
||||||
|
@ -223,6 +257,7 @@ namespace winsw
|
||||||
// Else just keep going
|
// Else just keep going
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
string? startarguments = _descriptor.Startarguments;
|
string? startarguments = _descriptor.Startarguments;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
#if VNEXT
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
#endif
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using winsw.Util;
|
using winsw.Util;
|
||||||
|
|
||||||
|
@ -103,9 +106,13 @@ namespace winsw
|
||||||
/// <exception cref="WebException">
|
/// <exception cref="WebException">
|
||||||
/// Download failure. FailOnError flag should be processed outside.
|
/// Download failure. FailOnError flag should be processed outside.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
|
#if VNEXT
|
||||||
|
public async Task PerformAsync()
|
||||||
|
#else
|
||||||
public void Perform()
|
public void Perform()
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
WebRequest req = WebRequest.Create(From);
|
WebRequest request = WebRequest.Create(From);
|
||||||
|
|
||||||
switch (Auth)
|
switch (Auth)
|
||||||
{
|
{
|
||||||
|
@ -114,43 +121,57 @@ namespace winsw
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AuthType.sspi:
|
case AuthType.sspi:
|
||||||
req.UseDefaultCredentials = true;
|
request.UseDefaultCredentials = true;
|
||||||
req.PreAuthenticate = true;
|
request.PreAuthenticate = true;
|
||||||
req.Credentials = CredentialCache.DefaultCredentials;
|
request.Credentials = CredentialCache.DefaultCredentials;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AuthType.basic:
|
case AuthType.basic:
|
||||||
SetBasicAuthHeader(req, Username!, Password!);
|
SetBasicAuthHeader(request, Username!, Password!);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new WebException("Code defect. Unsupported authentication type: " + Auth);
|
throw new WebException("Code defect. Unsupported authentication type: " + Auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebResponse rsp = req.GetResponse();
|
string tmpFilePath = To + ".tmp";
|
||||||
FileStream tmpstream = new FileStream(To + ".tmp", FileMode.Create);
|
#if VNEXT
|
||||||
CopyStream(rsp.GetResponseStream(), tmpstream);
|
using (WebResponse response = await request.GetResponseAsync())
|
||||||
// only after we successfully downloaded a file, overwrite the existing one
|
#else
|
||||||
|
using (WebResponse response = request.GetResponse())
|
||||||
|
#endif
|
||||||
|
using (Stream responseStream = response.GetResponseStream())
|
||||||
|
using (FileStream tmpStream = new FileStream(tmpFilePath, FileMode.Create))
|
||||||
|
{
|
||||||
|
#if VNEXT
|
||||||
|
await responseStream.CopyToAsync(tmpStream);
|
||||||
|
#elif NET20
|
||||||
|
CopyStream(responseStream, tmpStream);
|
||||||
|
#else
|
||||||
|
responseStream.CopyTo(tmpStream);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NETCOREAPP
|
||||||
|
File.Move(tmpFilePath, To, true);
|
||||||
|
#else
|
||||||
if (File.Exists(To))
|
if (File.Exists(To))
|
||||||
File.Delete(To);
|
File.Delete(To);
|
||||||
|
|
||||||
File.Move(To + ".tmp", To);
|
File.Move(tmpFilePath, To);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#if NET20
|
||||||
|
|
||||||
private static void CopyStream(Stream i, Stream o)
|
private static void CopyStream(Stream source, Stream destination)
|
||||||
{
|
{
|
||||||
byte[] buf = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
while (true)
|
int read;
|
||||||
|
while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
|
||||||
{
|
{
|
||||||
int len = i.Read(buf, 0, buf.Length);
|
destination.Write(buffer, 0, read);
|
||||||
if (len <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
o.Write(buf, 0, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i.Close();
|
|
||||||
o.Close();
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue