Files
duplicati/Duplicati/Library/Main/AsyncDownloader.cs
T

152 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Duplicati.Library.Main.Database;
namespace Duplicati.Library.Main
{
internal interface IAsyncDownloadedFile : IRemoteVolume
{
Library.Utility.TempFile TempFile { get; }
}
internal class AsyncDownloader : IEnumerable<IAsyncDownloadedFile>
{
private class AsyncDownloaderEnumerator : IEnumerator<IAsyncDownloadedFile>
{
private class AsyncDownloadedFile : IAsyncDownloadedFile
{
private Exception m_exception;
private Library.Utility.TempFile m_file;
public string Name { get; private set; }
public string Hash { get; private set; }
public long Size { get; private set; }
public void DisposeTempFile()
{
if (m_file != null)
try { m_file.Dispose(); }
finally { m_file = null; }
}
public Library.Utility.TempFile TempFile
{
get
{
if (m_exception != null)
throw m_exception;
return m_file;
}
}
public AsyncDownloadedFile(string name, string hash, long size, Library.Utility.TempFile tempfile, Exception exception)
{
this.Name = name;
this.Hash = hash;
this.Size = size;
m_exception = exception;
m_file = tempfile;
}
}
private IList<IRemoteVolume> m_volumes;
private BackendManager.IDownloadWaitHandle m_handle;
private BackendManager m_backend;
private int m_index;
private AsyncDownloadedFile m_current;
public AsyncDownloaderEnumerator(IList<IRemoteVolume> volumes, BackendManager backend)
{
m_volumes = volumes;
m_backend = backend;
m_index = 0;
}
public IAsyncDownloadedFile Current
{
get { return m_current; }
}
public void Dispose()
{
if (m_current != null)
{
m_current.DisposeTempFile();
m_current = null;
}
}
object System.Collections.IEnumerator.Current
{
get { return this.Current; }
}
public bool MoveNext()
{
if (m_current != null)
{
m_current.DisposeTempFile();
m_current = null;
}
if (m_index >= m_volumes.Count)
return false;
if (m_handle == null)
m_handle = m_backend.GetAsync(m_volumes[m_index].Name, m_volumes[m_index].Size, m_volumes[m_index].Hash);
string hash = null;
long size = -1;
Library.Utility.TempFile file = null;
Exception exception = null;
try
{
file = m_handle.Wait(out hash, out size);
}
catch (Exception ex)
{
exception = ex;
}
m_current = new AsyncDownloadedFile(m_volumes[m_index].Name, hash, size, file, exception);
m_handle = null;
m_index++;
if (m_index < m_volumes.Count)
m_handle = m_backend.GetAsync(m_volumes[m_index].Name, m_volumes[m_index].Size, m_volumes[m_index].Hash);
return true;
}
public void Reset()
{
throw new NotSupportedException("Cannot reset " + this.GetType().FullName);
}
}
private IList<IRemoteVolume> m_volumes;
private BackendManager m_backend;
public AsyncDownloader(IList<IRemoteVolume> volumes, BackendManager backend)
{
m_volumes = volumes;
m_backend = backend;
}
public IEnumerator<IAsyncDownloadedFile> GetEnumerator()
{
return new AsyncDownloaderEnumerator(m_volumes, m_backend);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}