Merge branch 'master' into feature/add-sqlite-cache-value
This commit is contained in:
@@ -37,7 +37,7 @@ var target_extensions = new[] {
|
||||
// ".css"
|
||||
}.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
File.WriteAllText(Path.Combine(startpath, "LICENSE.txt"), Fragments.GetLicenseTextWithPrefixedLines(string.Empty));
|
||||
File.WriteAllText(Path.Combine(startpath, "LICENSE"), Fragments.GetLicenseTextWithPrefixedLines(string.Empty));
|
||||
|
||||
var candidates = Directory.EnumerateFiles(startpath, "*", SearchOption.AllDirectories)
|
||||
.Where(x => target_extensions.Contains(Path.GetExtension(x) ?? string.Empty));
|
||||
|
||||
@@ -36,15 +36,6 @@ internal partial class BackendManager : IBackendManager
|
||||
/// </summary>
|
||||
private readonly Task queueRunner;
|
||||
|
||||
/// <summary>
|
||||
/// The last file read size
|
||||
/// </summary>
|
||||
public long LastReadSize { get; private set; }
|
||||
/// <summary>
|
||||
/// The last file write size
|
||||
/// </summary>
|
||||
public long LastWriteSize { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The execution context
|
||||
/// </summary>
|
||||
@@ -171,8 +162,7 @@ internal partial class BackendManager : IBackendManager
|
||||
Decrypt = true
|
||||
};
|
||||
await QueueTask(op).ConfigureAwait(false);
|
||||
(var file, var _, var downloadSize) = await op.GetResult().ConfigureAwait(false);
|
||||
LastReadSize = downloadSize;
|
||||
(var file, var _, var _) = await op.GetResult().ConfigureAwait(false);
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -192,8 +182,7 @@ internal partial class BackendManager : IBackendManager
|
||||
Decrypt = false
|
||||
};
|
||||
await QueueTask(op).ConfigureAwait(false);
|
||||
(var file, var _, var downloadSize) = await op.GetResult().ConfigureAwait(false);
|
||||
LastReadSize = downloadSize;
|
||||
(var file, var _, var _) = await op.GetResult().ConfigureAwait(false);
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -226,7 +215,6 @@ internal partial class BackendManager : IBackendManager
|
||||
};
|
||||
await QueueTask(op).ConfigureAwait(false);
|
||||
(var file, var downloadHash, var downloadSize) = await op.GetResult().ConfigureAwait(false);
|
||||
LastReadSize = downloadSize;
|
||||
return (file, downloadHash, downloadSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -660,6 +660,15 @@ SELECT ""BlocklistHash"".""BlocksetID"" FROM ""BlocklistHash"" WHERE ""Blocklist
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public long GetLastWrittenDBlockVolumeSize(IDbTransaction? transaction)
|
||||
{
|
||||
using (var cmd = m_connection.CreateCommand(transaction))
|
||||
return cmd.SetCommandAndParameters(@"SELECT ""Size"" FROM ""RemoteVolume"" WHERE ""State"" = @State AND ""Type"" = @Type ORDER BY ""ID"" DESC LIMIT 1")
|
||||
.SetParameterValue("@State", RemoteVolumeState.Uploaded.ToString())
|
||||
.SetParameterValue("@Type", RemoteVolumeType.Blocks.ToString())
|
||||
.ExecuteScalarInt64(-1);
|
||||
}
|
||||
|
||||
private long GetPreviousFilesetID(IDbCommand cmd)
|
||||
{
|
||||
return GetPreviousFilesetID(cmd, OperationTimestamp, m_filesetId, cmd.Transaction);
|
||||
|
||||
@@ -206,17 +206,17 @@ namespace Duplicati.Library.Main.Database
|
||||
return Library.Utility.Utility.EPOCH.AddSeconds(seconds);
|
||||
}
|
||||
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, IDbTransaction? transaction = null)
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string? hash, IDbTransaction? transaction = null)
|
||||
{
|
||||
UpdateRemoteVolume(name, state, size, hash, false, transaction);
|
||||
}
|
||||
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, IDbTransaction? transaction = null)
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string? hash, bool suppressCleanup, IDbTransaction? transaction = null)
|
||||
{
|
||||
UpdateRemoteVolume(name, state, size, hash, suppressCleanup, new TimeSpan(0), transaction);
|
||||
}
|
||||
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, TimeSpan deleteGraceTime, IDbTransaction? transaction = null)
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string? hash, bool suppressCleanup, TimeSpan deleteGraceTime, IDbTransaction? transaction = null)
|
||||
{
|
||||
m_updateremotevolumeCommand.Transaction = transaction;
|
||||
var c = m_updateremotevolumeCommand.SetParameterValue("@OperationID", m_operationid)
|
||||
@@ -391,7 +391,7 @@ namespace Duplicati.Library.Main.Database
|
||||
/// <param name="operation">The operation performed</param>
|
||||
/// <param name="path">The path involved</param>
|
||||
/// <param name="data">Any data relating to the operation</param>
|
||||
public void LogRemoteOperation(string operation, string path, string data, IDbTransaction transaction)
|
||||
public void LogRemoteOperation(string operation, string path, string? data, IDbTransaction? transaction)
|
||||
{
|
||||
m_insertremotelogCommand
|
||||
.SetParameterValue("@OperationID", m_operationid)
|
||||
@@ -1434,7 +1434,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
}
|
||||
}
|
||||
|
||||
public void RenameRemoteFile(string oldname, string newname, IDbTransaction transaction)
|
||||
public void RenameRemoteFile(string oldname, string newname, IDbTransaction? transaction)
|
||||
{
|
||||
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
|
||||
using (var cmd = m_connection.CreateCommand(tr.Parent))
|
||||
|
||||
@@ -126,16 +126,6 @@ internal interface IBackendManager : IDisposable
|
||||
/// <returns>The downloaded files, hash, size, and name</returns>
|
||||
IAsyncEnumerable<(TempFile File, string Hash, long Size, string Name)> GetFilesOverlappedAsync(IEnumerable<IRemoteVolume> volumes, CancellationToken cancelToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the last read operation
|
||||
/// </summary>
|
||||
long LastReadSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the last write operation
|
||||
/// </summary>
|
||||
long LastWriteSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the database messages to the database
|
||||
/// </summary>
|
||||
|
||||
@@ -595,7 +595,7 @@ namespace Duplicati.Library.Main.Operation
|
||||
return new AggregateException(ex.First().Message, ex);
|
||||
}
|
||||
|
||||
private static async Task<long> FlushBackend(Backup.BackupDatabase database, BackupResults result, IBackendManager backendManager)
|
||||
private static async Task FlushBackend(Backup.BackupDatabase database, BackupResults result, IBackendManager backendManager)
|
||||
{
|
||||
// Wait for upload completion
|
||||
result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_WaitForUpload);
|
||||
@@ -605,14 +605,10 @@ namespace Duplicati.Library.Main.Operation
|
||||
await database.FlushBackendMessagesAndCommitAsync(backendManager).ConfigureAwait(false);
|
||||
await backendManager.WaitForEmptyAsync(result.TaskControl.ProgressToken).ConfigureAwait(false);
|
||||
await database.FlushBackendMessagesAndCommitAsync(backendManager).ConfigureAwait(false);
|
||||
// Grab the size of the last uploaded volume
|
||||
return backendManager.LastWriteSize;
|
||||
}
|
||||
catch (RetiredException)
|
||||
{
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public async Task RunAsync(string[] sources, IBackendManager backendManager, IFilter filter)
|
||||
@@ -719,7 +715,7 @@ namespace Duplicati.Library.Main.Operation
|
||||
|
||||
// Wait for upload completion
|
||||
m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_WaitForUpload);
|
||||
var lastVolumeSize = await FlushBackend(db, m_result, backendManager).ConfigureAwait(false);
|
||||
await FlushBackend(db, m_result, backendManager).ConfigureAwait(false);
|
||||
|
||||
if (!m_options.Dryrun)
|
||||
database.TerminatedWithActiveUploads = false;
|
||||
@@ -730,7 +726,10 @@ namespace Duplicati.Library.Main.Operation
|
||||
{
|
||||
// If this throws, we should roll back the transaction
|
||||
if (await m_result.TaskControl.ProgressRendevouz().ConfigureAwait(false))
|
||||
{
|
||||
var lastVolumeSize = m_database.GetLastWrittenDBlockVolumeSize(rtr.Transaction);
|
||||
await CompactIfRequired(backendManager, rtr, lastVolumeSize);
|
||||
}
|
||||
|
||||
if (m_options.UploadVerificationFile && await m_result.TaskControl.ProgressRendevouz().ConfigureAwait(false))
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<Link>changelog.txt</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\LICENSE.txt">
|
||||
<Content Include="..\..\LICENSE">
|
||||
<Link>licenses\license.txt</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
translate-params-mail1="'mailto:kenneth@duplicati.com'"
|
||||
translate-params-mail2="'mailto:rene@duplicati.com'"
|
||||
translate-params-websitename="'duplicati.com'"
|
||||
translate-params-websitelink="'http://www.duplicati.com'"
|
||||
translate-params-websitelink="'https://duplicati.com'"
|
||||
translate-params-licensename="'MIT license'"
|
||||
translate-params-licenselink="'https://raw.githubusercontent.com/duplicati/duplicati/master/LICENSE.txt'"
|
||||
translate-params-licenselink="'https://raw.githubusercontent.com/duplicati/duplicati/master/LICENSE'"
|
||||
>
|
||||
{{appname}} was primarily developed by <a href="{{mail1}}">{{dev1}}</a> and <a href="{{mail2}}">{{dev2}}</a>. {{appname}} can be downloaded from <a href="{{websitelink}}">{{websitename}}</a>. {{appname}} is licensed under the <a href="{{licenselink}}">{{licensename}}</a>.
|
||||
</div>
|
||||
|
||||
@@ -741,6 +741,9 @@ namespace Duplicati.UnitTest
|
||||
using (var c = new Controller("file://" + TARGETFOLDER, testopts, null))
|
||||
TestUtils.AssertResults(c.Backup(new string[] { DATAFOLDER }));
|
||||
|
||||
// Ensure that the target folder only has a single dlist file
|
||||
Assert.AreEqual(1, Directory.EnumerateFiles(TARGETFOLDER, "*.dlist.*").Count(), "There should be only one dlist file in the target folder");
|
||||
|
||||
// Make a new backup that fails uploading a dblock file
|
||||
ModifySourceFiles();
|
||||
|
||||
@@ -753,6 +756,7 @@ namespace Duplicati.UnitTest
|
||||
var secondUploadCompleted = false;
|
||||
|
||||
// Fail the compact after the first dblock put is completed
|
||||
var uploads = new List<string>();
|
||||
DeterministicErrorBackend.ErrorGenerator = (DeterministicErrorBackend.BackendAction action, string remotename) =>
|
||||
{
|
||||
if (action.IsGetOperation)
|
||||
@@ -783,6 +787,11 @@ namespace Duplicati.UnitTest
|
||||
|
||||
Assert.That(secondUploadStarted, Is.True, "Second upload was not started");
|
||||
Assert.That(secondUploadCompleted, Is.True, "Second upload was not started");
|
||||
Assert.That(hasFailed, Is.True, "Failed to fail the upload");
|
||||
Assert.That(!uploads.Any(x => x.Contains("dlist")), Is.True, "Upload of dlist file was not skipped");
|
||||
|
||||
// Ensure that the target folder only has a single dlist file
|
||||
Assert.AreEqual(1, Directory.EnumerateFiles(TARGETFOLDER, "*.dlist.*").Count(), $"There should be only one dlist file in the target folder: {string.Join(", ", uploads)}");
|
||||
|
||||
// Create a regular backup
|
||||
using (var c = new Controller("file://" + TARGETFOLDER, testopts, null))
|
||||
|
||||
@@ -819,7 +819,7 @@ public static partial class Command
|
||||
|
||||
// Write the license file
|
||||
File.Copy(
|
||||
Path.Combine(baseDir, "LICENSE.txt"),
|
||||
Path.Combine(baseDir, "LICENSE"),
|
||||
EnsureFolderForFile(
|
||||
Path.Combine(pkgroot, "usr", "share", "doc", "duplicati", "copyright")
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user