Improve SQL logging

This PR improves SQL logging by capturing many places where the calls would previously just hit the database and not produce any logging output.
This commit is contained in:
Kenneth Skovhede
2026-05-06 10:52:58 +02:00
parent 373f4d2102
commit 4244e71fee
15 changed files with 278 additions and 242 deletions
@@ -80,7 +80,7 @@ public static class ChangeStatistics
")
.SetParameterValue("@LastFilesetId", previousFilesetId)
.SetParameterValue("@CurrentFilesetId", currentFilesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Index for fast comparison
@@ -434,7 +434,7 @@ namespace Duplicati.Library.Main.Database
RemoteVolumeState.Deleted,
RemoteVolumeState.Deleting
])
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
var deletedBlocks = await cmd.ExecuteScalarInt64Async(@$"
@@ -1584,7 +1584,7 @@ namespace Duplicati.Library.Main.Database
")
.SetParameterValue("@PreviousFilesetId", lastFilesetId)
.SetParameterValue("@CurrentFilesetId", fileSetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// now we need to remove, from the above, any entries that were enumerated by the
@@ -1614,16 +1614,17 @@ namespace Duplicati.Library.Main.Database
ON ""f"".""BlocksetID"" = ""bs"".""ID"";
");
await foreach (var row in cmd.ExecuteReaderEnumerableAsync(token).ConfigureAwait(false))
{
var path = row.ConvertValueToString(0) ?? throw new Exception("Unexpected null value for path");
var size = row.ConvertValueToInt64(3);
using (new Logging.Timer(LOGTAG, "DeletePreviousFiles", $"Deleting files not included in the current backup"))
await foreach (var row in cmd.ExecuteReaderEnumerableAsync(token).ConfigureAwait(false))
{
var path = row.ConvertValueToString(0) ?? throw new Exception("Unexpected null value for path");
var size = row.ConvertValueToInt64(3);
if (exclusionPredicate(path, size))
await cmdDelete.SetParameterValue("@FileId", row.ConvertValueToInt64(1))
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
if (exclusionPredicate(path, size))
await cmdDelete.SetParameterValue("@FileId", row.ConvertValueToInt64(1))
.ExecuteNonQueryAsync(token) // Not logging because we log the full operation
.ConfigureAwait(false);
}
// now copy the temporary table into the FileSetEntry table
await cmd.SetCommandAndParameters($@"
@@ -1639,7 +1640,7 @@ namespace Duplicati.Library.Main.Database
FROM ""{tempFileSetTable}""
")
.SetParameterValue("@FilesetId", fileSetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await m_rtr.CommitAsync(token).ConfigureAwait(false);
@@ -1741,7 +1742,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Hash", blockkey)
.SetParameterValue("@Size", size)
.SetParameterValue("@PreviousVolumeId", sourcevolumeid)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -1870,10 +1871,11 @@ namespace Duplicati.Library.Main.Database
/// <exception cref="Exception">Thrown if unable to add change journal entry.</exception>
public async Task CreateChangeJournalData(IEnumerable<Interface.USNJournalDataEntry> data, CancellationToken token)
{
foreach (var entry in data)
{
await using var cmd = m_connection.CreateCommand(m_rtr);
var c = await cmd.SetCommandAndParameters(@"
using (new Logging.Timer(LOGTAG, "CreateChangeJournalData", "Inserting USN entries"))
foreach (var entry in data)
{
await using var cmd = m_connection.CreateCommand(m_rtr);
var c = await cmd.SetCommandAndParameters(@"
INSERT INTO ""ChangeJournalData"" (
""FilesetID"",
""VolumeName"",
@@ -1889,17 +1891,17 @@ namespace Duplicati.Library.Main.Database
@ConfigHash
);
")
.SetParameterValue("@FilesetId", m_filesetId)
.SetParameterValue("@VolumeName", entry.Volume)
.SetParameterValue("@JournalId", entry.JournalId)
.SetParameterValue("@NextUsn", entry.NextUsn)
.SetParameterValue("@ConfigHash", entry.ConfigHash)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
.SetParameterValue("@FilesetId", m_filesetId)
.SetParameterValue("@VolumeName", entry.Volume)
.SetParameterValue("@JournalId", entry.JournalId)
.SetParameterValue("@NextUsn", entry.NextUsn)
.SetParameterValue("@ConfigHash", entry.ConfigHash)
.ExecuteNonQueryAsync(token) // Not logging, as we log the whole operation
.ConfigureAwait(false);
if (c != 1)
throw new Exception("Unable to add change journal entry");
}
if (c != 1)
throw new Exception("Unable to add change journal entry");
}
await m_rtr.CommitAsync(token: token).ConfigureAwait(false);
}
@@ -1913,10 +1915,11 @@ namespace Duplicati.Library.Main.Database
/// <returns>A task that completes when the data is added.</returns>
public async Task UpdateChangeJournalData(IEnumerable<Interface.USNJournalDataEntry> data, long fileSetId, CancellationToken token)
{
foreach (var entry in data)
{
await using var cmd = m_connection.CreateCommand();
await cmd.SetCommandAndParameters(@"
using (new Logging.Timer(LOGTAG, "UpdateChangeJournalData", "Updating USN entries"))
foreach (var entry in data)
{
await using var cmd = m_connection.CreateCommand();
await cmd.SetCommandAndParameters(@"
UPDATE ""ChangeJournalData""
SET ""NextUSN"" = @NextUsn
WHERE
@@ -1924,14 +1927,14 @@ namespace Duplicati.Library.Main.Database
AND ""VolumeName"" = @VolumeName
AND ""JournalID"" = @JournalId;
")
.SetTransaction(m_rtr)
.SetParameterValue("@NextUsn", entry.NextUsn)
.SetParameterValue("@FilesetId", fileSetId)
.SetParameterValue("@VolumeName", entry.Volume)
.SetParameterValue("@JournalId", entry.JournalId)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
.SetTransaction(m_rtr)
.SetParameterValue("@NextUsn", entry.NextUsn)
.SetParameterValue("@FilesetId", fileSetId)
.SetParameterValue("@VolumeName", entry.Volume)
.SetParameterValue("@JournalId", entry.JournalId)
.ExecuteNonQueryAsync(token) // Not logging, as we log the whole operation
.ConfigureAwait(false);
}
await m_rtr.CommitAsync(token: token).ConfigureAwait(false);
}
@@ -1989,7 +1992,7 @@ namespace Duplicati.Library.Main.Database
var deletedCount = await cmd
.SetCommandAndParameters(sql)
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (deletedCount > 0)
@@ -107,7 +107,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@StartPath", !OperatingSystem.IsWindows() ? "/" : "X:\\")
.SetParameterValue("@DirSep", Util.DirectorySeparatorString)
.SetParameterValue("@FileExt", ".bin")
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
/*long id = 1;
@@ -653,7 +653,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.SetParameterValue("@Name", name)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -673,7 +673,7 @@ namespace Duplicati.Library.Main.Database
c = await cmd.SetTransaction(m_rtr)
.SetParameterValue("@DeleteGraceTime", Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(DateTime.UtcNow + deleteGraceTime))
.SetParameterValue("@Name", name)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -692,7 +692,7 @@ namespace Duplicati.Library.Main.Database
c = await cmd.SetTransaction(m_rtr)
.SetParameterValue("@ArchiveTime", setArchived.Value ? Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(DateTime.UtcNow) : 0)
.SetParameterValue("@Name", name)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -936,7 +936,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Operation", operation)
.SetParameterValue("@Path", path)
.SetParameterValue("@Data", data)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -957,7 +957,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Type", type)
.SetParameterValue("@Message", message)
.SetParameterValue("@Exception", exception?.ToString())
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -983,7 +983,7 @@ namespace Duplicati.Library.Main.Database
var c = await cmd.SetTransaction(m_rtr)
.SetParameterValue("@Name", name)
.SetParameterValue("@State", state.ToString())
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -1053,7 +1053,7 @@ namespace Duplicati.Library.Main.Database
await deletecmd.ExpandInClauseParameterMssqliteAsync("@VolumeNames", tmptable, token)
.ConfigureAwait(false);
await deletecmd
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
var volIdsSubQuery = $@"
@@ -1299,7 +1299,7 @@ namespace Duplicati.Library.Main.Database
RemoteVolumeState.Verified.ToString(),
RemoteVolumeState.Temporary.ToString()
])
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await deletecmd.ExecuteNonQueryAsync($@"
@@ -1340,14 +1340,14 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_rtr)
.SetParameterValue("@Now", Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(DateTime.UtcNow))
.SetParameterValue("@State", RemoteVolumeState.Deleted.ToString());
foreach (var name in names)
{
await m_removeremotevolumeCommand
.SetTransaction(m_rtr)
.SetParameterValue("@Name", name)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
using (new Logging.Timer(LOGTAG, "RemoveRemoteVolumes", "Removing remote volumes"))
foreach (var name in names)
await m_removeremotevolumeCommand
.SetTransaction(m_rtr)
.SetParameterValue("@Name", name)
.ExecuteNonQueryAsync(token) // Not logging because we log the whole operation
.ConfigureAwait(false);
// Validate before commiting changes
var nonAttachedFiles = await deletecmd.ExecuteScalarInt64Async(@"
@@ -1695,9 +1695,10 @@ namespace Duplicati.Library.Main.Database
", token)
.ConfigureAwait(false);
foreach (var kp in options)
{
await cmd.SetCommandAndParameters(@"
using (new Logging.Timer(LOGTAG, "SetDbOptions", "Setting database options"))
foreach (var kp in options)
{
await cmd.SetCommandAndParameters(@"
INSERT INTO ""Configuration"" (
""Key"",
""Value""
@@ -1707,11 +1708,11 @@ namespace Duplicati.Library.Main.Database
@Value
)
")
.SetParameterValue("@Key", kp.Key)
.SetParameterValue("@Value", kp.Value)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
.SetParameterValue("@Key", kp.Key)
.SetParameterValue("@Value", kp.Value)
.ExecuteNonQueryAsync(token) // Not logging, as we log the whole operation
.ConfigureAwait(false);
}
}
/// <summary>
@@ -2598,7 +2599,7 @@ namespace Duplicati.Library.Main.Database
var c = await cmd.SetTransaction(m_rtr)
.SetParameterValue("@VolumeId", volumeid)
.SetParameterValue("@FilesetId", filesetid)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -2635,7 +2636,7 @@ namespace Duplicati.Library.Main.Database
await cmd.SetTransaction(m_rtr)
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -2698,7 +2699,7 @@ namespace Duplicati.Library.Main.Database
.ConfigureAwait(false);
await cmd.SetTransaction(db.Transaction)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
return ftt;
@@ -2715,7 +2716,7 @@ namespace Duplicati.Library.Main.Database
.ConfigureAwait(false);
await cmd.SetTransaction(db.Transaction)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
cmd.SetCommandAndParameters($@"
@@ -2730,6 +2731,7 @@ namespace Duplicati.Library.Main.Database
.ConfigureAwait(false);
c2.SetTransaction(db.Transaction);
using (new Logging.Timer(LOGTAG, "CreateFilteredFilenameTable", "Filtering paths"))
await using (var rd = await c2.ExecuteReaderAsync(token).ConfigureAwait(false))
while (await rd.ReadAsync(token).ConfigureAwait(false))
{
@@ -2738,7 +2740,7 @@ namespace Duplicati.Library.Main.Database
{
await cmd
.SetParameterValue("@Path", p)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(token) // Not logging as we log the whole operation
.ConfigureAwait(false);
}
}
@@ -2833,7 +2835,7 @@ namespace Duplicati.Library.Main.Database
var c = await cmd.SetTransaction(m_rtr)
.SetParameterValue("@Newname", newname)
.SetParameterValue("@Oldname", oldname)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -2848,7 +2850,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""Name"" = @Name
")
.SetParameterValue("@Name", newname)
.ExecuteScalarAsync(token)
.ExecuteScalarAsync(true, token)
.ConfigureAwait(false)
)?.ToString() ?? "",
true
@@ -2926,7 +2928,7 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_rtr)
.SetParameterValue("@IndexVolumeId", indexVolumeID)
.SetParameterValue("@BlockVolumeId", blockVolumeID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -3045,7 +3047,7 @@ namespace Duplicati.Library.Main.Database
await cmd.SetTransaction(m_rtr)
.SetParameterValue("@FilesetId", fileSetId)
.SetParameterValue("@IsFullBackup", isFullBackup ? BackupType.FULL_BACKUP : BackupType.PARTIAL_BACKUP)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -3065,7 +3067,7 @@ namespace Duplicati.Library.Main.Database
await cmd.SetTransaction(m_rtr)
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -3197,7 +3199,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""Timestamp"" < @Timestamp
")
.SetParameterValue("@Timestamp", t)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await cmd.SetCommandAndParameters(@"
@@ -3205,7 +3207,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""Timestamp"" < @Timestamp
")
.SetParameterValue("@Timestamp", t)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await m_rtr.CommitAsync(token: token).ConfigureAwait(false);
@@ -3221,7 +3223,7 @@ namespace Duplicati.Library.Main.Database
await m_removedeletedremotevolumeCommand
.SetTransaction(m_rtr)
.SetParameterValue("@Now", Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(threshold))
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await m_rtr.CommitAsync(token: token).ConfigureAwait(false);
@@ -134,7 +134,7 @@ namespace Duplicati.Library.Main.Database
.ExpandInClauseParameterMssqliteAsync("@Timestamps", tempTable, token)
.ConfigureAwait(false)
)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (deleted != toDelete.Length)
@@ -267,7 +267,7 @@ namespace Duplicati.Library.Main.Database
RemoteVolumeState.Temporary.ToString(),
RemoteVolumeState.Deleting.ToString()
])
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (deleted != updated)
@@ -540,7 +540,7 @@ namespace Duplicati.Library.Main.Database
RemoteVolumeState.Uploaded.ToString(),
RemoteVolumeState.Verified.ToString()
])
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
cmd.SetCommandAndParameters($@"
@@ -901,7 +901,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@VolumeId", volumeID)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -931,7 +931,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""VolumeID"" = @VolumeId
")
.SetParameterValue("@VolumeId", deletedVolume.ID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await using (var tempTable = await TemporaryDbValueList.CreateAsync(this, volumeIdsToBeRemoved, token).ConfigureAwait(false))
@@ -953,7 +953,7 @@ namespace Duplicati.Library.Main.Database
.ExpandInClauseParameterMssqliteAsync("@VolumeIds", tempTable, token)
.ConfigureAwait(false)
)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
var targetCount = await cmd.ExecuteScalarInt64Async($@"
@@ -984,7 +984,7 @@ namespace Duplicati.Library.Main.Database
AND ""Block"".""ID"" IN (SELECT ""BlockID"" FROM ""{replacementBlocks}"")
")
.SetParameterValue("@VolumeId", deletedVolume.ID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
var deleteCount = await cmd.ExecuteNonQueryAsync(@$"
@@ -1017,7 +1017,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""VolumeID"" = @VolumeId
")
.SetParameterValue("@VolumeId", deletedVolume.ID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
finally
@@ -300,7 +300,7 @@ namespace Duplicati.Library.Main.Database
.SetCommandAndParameters(INSERT_BROKEN_IDS(tablename, IDfieldname))
.SetParameterValue("@FilesetId", filesetid);
await cmd.ExecuteNonQueryAsync(token)
await cmd.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -339,7 +339,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@EmptyBlocksetID", emptyBlocksetId)
.SetParameterValue("@FilesetID", filesetId);
return await cmd.ExecuteNonQueryAsync(token).ConfigureAwait(false);
return await cmd.ExecuteNonQueryAsync(true, token).ConfigureAwait(false);
}
/// <summary>
@@ -375,7 +375,7 @@ namespace Duplicati.Library.Main.Database
.ExpandInClauseParameterMssqliteAsync("@Names", tmptable, token)
.ConfigureAwait(false)
)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
var volIdsSubQuery = $@"
@@ -36,6 +36,10 @@ namespace Duplicati.Library.Main.Database
/// </summary>
internal class LocalListChangesDatabase : LocalDatabase
{
/// <summary>
/// The log tag for this class.
/// </summary>
private static readonly string LOGTAG = Logging.Log.LogTagFromType<LocalListChangesDatabase>();
/// <summary>
/// Creates a new instance of the <see cref="LocalListChangesDatabase"/> class.
@@ -70,9 +74,10 @@ namespace Duplicati.Library.Main.Database
/// <param name="size">The size of the file or folder.</param>
/// <param name="type">The type of the element (file, folder, symlink).</param>
/// <param name="asNew">If true, adds to the current table; otherwise, adds to the previous table.</param>
/// <param name="logQuery">If true, logs the SQL query.</param>
/// <param name="token">A cancellation token to cancel the operation.</param>
/// <returns>A task that completes when the element is added.</returns>
Task AddElement(string path, string filehash, string metahash, long size, Interface.ListChangesElementType type, bool asNew, CancellationToken token);
Task AddElement(string path, string filehash, string metahash, long size, Interface.ListChangesElementType type, bool asNew, bool logQuery, CancellationToken token);
/// <summary>
/// Adds elements from the database to the temporary storage.
@@ -419,7 +424,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""A"".""FilesetID"" = @FilesetId
")
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
else if (Library.Utility.Utility.IsFSCaseSensitive && filter is FilterExpression expression && expression.Type == Duplicati.Library.Utility.FilterType.Simple)
@@ -443,11 +448,12 @@ namespace Duplicati.Library.Main.Database
.PrepareAsync(token)
.ConfigureAwait(false);
foreach (var s in p)
await cmd
.SetParameterValue("@Path", s)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
using (new Logging.Timer(LOGTAG, "AddFromDb", $"Inserting {p.Length} paths into {filenamestable}"))
foreach (var s in p)
await cmd
.SetParameterValue("@Path", s)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
string whereClause;
if (expression.Result)
@@ -490,7 +496,7 @@ namespace Duplicati.Library.Main.Database
WHERE {whereClause}
")
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await cmd
@@ -538,27 +544,28 @@ namespace Duplicati.Library.Main.Database
.ExecuteReaderAsync(token)
.ConfigureAwait(false);
while (await rd.ReadAsync(token).ConfigureAwait(false))
{
rd.GetValues(values);
var path = values[0] as string;
if (path != null && FilterExpression.Matches(filter, path.ToString()))
using (new Logging.Timer(LOGTAG, "AddFromDb", $"Evaluating paths and updating table"))
while (await rd.ReadAsync(token).ConfigureAwait(false))
{
await cmd2
.SetParameterValue("@Path", values[0])
.SetParameterValue("@FileHash", values[1])
.SetParameterValue("@MetaHash", values[2])
.SetParameterValue("@Size", values[3])
.SetParameterValue("@Type", values[4])
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
rd.GetValues(values);
var path = values[0] as string;
if (path != null && FilterExpression.Matches(filter, path.ToString()))
{
await cmd2
.SetParameterValue("@Path", values[0])
.SetParameterValue("@FileHash", values[1])
.SetParameterValue("@MetaHash", values[2])
.SetParameterValue("@Size", values[3])
.SetParameterValue("@Type", values[4])
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
}
}
}
}
/// <inheritdoc/>
public async Task AddElement(string path, string filehash, string metahash, long size, Interface.ListChangesElementType type, bool asNew, CancellationToken token)
public async Task AddElement(string path, string filehash, string metahash, long size, Interface.ListChangesElementType type, bool asNew, bool logQuery, CancellationToken token)
{
var cmd = asNew ? m_insertCurrentElementCommand : m_insertPreviousElementCommand;
await cmd
@@ -567,7 +574,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@MetaHash", metahash)
.SetParameterValue("@Size", size)
.SetParameterValue("@Type", (int)type)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(logQuery, token)
.ConfigureAwait(false);
}
@@ -368,7 +368,7 @@ namespace Duplicati.Library.Main.Database
WHERE SUBSTR(""Path"", 1, {Library.Utility.Utility.FormatInvariantValue(prefixrule.Length)}) != @Rule
")
.SetParameterValue("@Rule", prefixrule)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Then we recursively find the largest prefix
@@ -563,11 +563,12 @@ namespace Duplicati.Library.Main.Database
VALUES (@Path)
");
await foreach (var n in SelectFolderEntries(cmd, pathprefix, tmpnames.Tablename, token).Distinct().ConfigureAwait(false))
await c2
.SetParameterValue("@Path", n)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
using (new Logging.Timer(LOGTAG, "ListFolderContents", "Inserting paths into table"))
await foreach (var n in SelectFolderEntries(cmd, pathprefix, tmpnames.Tablename, token).Distinct().ConfigureAwait(false))
await c2
.SetParameterValue("@Path", n)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
await c2.ExecuteNonQueryAsync($@"
CREATE INDEX ""{tbname}_PathIndex""
@@ -73,7 +73,7 @@ namespace Duplicati.Library.Main.Database
cmd.SetParameterValue("@Name", name);
cmd.SetParameterValue("@LockExpirationTime", Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(lockExpirationTime));
var c = await cmd.ExecuteNonQueryAsync(token).ConfigureAwait(false);
var c = await cmd.ExecuteNonQueryAsync(true, token).ConfigureAwait(false);
if (c != 1)
throw new Exception($"Unexpected number of remote volumes updated: {c}, expected 1");
}
@@ -36,6 +36,11 @@ namespace Duplicati.Library.Main.Database
/// </summary>
internal class LocalPurgeDatabase : LocalDeleteDatabase
{
/// <summary>
/// The log tag used for logging
/// </summary>
private static readonly string LOGTAG = Logging.Log.LogTagFromType<LocalPurgeDatabase>();
/// <summary>
/// Creates a new instance of the <see cref="LocalPurgeDatabase"/> class.
/// </summary>
@@ -300,10 +305,11 @@ namespace Duplicati.Library.Main.Database
.PrepareAsync(token)
.ConfigureAwait(false);
foreach (var s in p)
await cmd.SetParameterValue("@Path", s)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
using (new Logging.Timer(LOGTAG, "ApplyFilter", "Inserting paths into table"))
foreach (var s in p)
await cmd.SetParameterValue("@Path", s)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
await cmd.SetCommandAndParameters($@"
INSERT INTO ""{m_tablename}"" (""FileID"")
@@ -317,7 +323,7 @@ namespace Duplicati.Library.Main.Database
AND ""B"".""Path"" IN ""{filenamestable}""
")
.SetParameterValue("@FilesetId", ParentID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await cmd
@@ -350,17 +356,20 @@ namespace Duplicati.Library.Main.Database
")
.SetParameterValue("@FilesetId", ParentID);
await using var rd = await cmd.ExecuteReaderAsync(token).ConfigureAwait(false);
while (await rd.ReadAsync(token).ConfigureAwait(false))
using (new Logging.Timer(LOGTAG, "ApplyFilter", "Iterating files with filter"))
{
rd.GetValues(values);
var path = values[0] as string;
if (path != null && Library.Utility.FilterExpression.Matches(filter, path.ToString()))
await using var rd = await cmd.ExecuteReaderAsync(token).ConfigureAwait(false);
while (await rd.ReadAsync(token).ConfigureAwait(false))
{
await cmd2
.SetParameterValue("@FileId", values[1])
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
rd.GetValues(values);
var path = values[0] as string;
if (path != null && Library.Utility.FilterExpression.Matches(filter, path.ToString()))
{
await cmd2
.SetParameterValue("@FileId", values[1])
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
}
}
}
@@ -480,7 +489,7 @@ namespace Duplicati.Library.Main.Database
")
.SetParameterValue("@TargetFilesetId", filesetid)
.SetParameterValue("@SourceFilesetId", ParentID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
return new Tuple<long, long>(remotevolid, filesetid);
@@ -873,7 +873,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@FilesetId", filesetid)
.SetParameterValue("@FileId", fileid)
.SetParameterValue("@LastModified", time.ToUniversalTime().Ticks)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -953,21 +953,22 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_rtr)
.SetParameterValue("@BlocksetId", blocksetid);
foreach (var hash in blocklisthashes)
{
if (!string.IsNullOrEmpty(hash))
using (new Logging.Timer(LOGTAG, "AddBlockset", "Inserting blocklist hashes"))
foreach (var hash in blocklisthashes)
{
c++;
if (c <= expectedblocklisthashes)
if (!string.IsNullOrEmpty(hash))
{
await m_insertBlocklistHashCommand
.SetParameterValue("@Index", index++)
.SetParameterValue("@Hash", hash)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
c++;
if (c <= expectedblocklisthashes)
{
await m_insertBlocklistHashCommand
.SetParameterValue("@Index", index++)
.SetParameterValue("@Hash", hash)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
}
}
}
}
if (c != expectedblocklisthashes)
@@ -1008,7 +1009,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.SetParameterValue("@VolumeId", volumeID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
return (anyChange, true);
@@ -1021,7 +1022,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@VolumeId", volumeID)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -1036,7 +1037,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.SetParameterValue("@VolumeId", volumeID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
return (anyChange, false);
@@ -1059,7 +1060,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@FileHash", filehash)
.SetParameterValue("@BlockHash", blockhash)
.SetParameterValue("@BlockSize", blocksize)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -1076,7 +1077,7 @@ namespace Duplicati.Library.Main.Database
var r = await m_findTempBlockListHashCommand
.SetTransaction(m_rtr)
.SetParameterValue("@BlocklistHash", hash)
.ExecuteScalarAsync(token)
.ExecuteScalarAsync(true, token)
.ConfigureAwait(false);
if (r != null && r != DBNull.Value)
@@ -1093,7 +1094,7 @@ namespace Duplicati.Library.Main.Database
await m_insertTempBlockListHash
.SetParameterValue("@BlockHash", s)
.SetParameterValue("@Index", index++)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -1572,7 +1573,7 @@ namespace Duplicati.Library.Main.Database
update.Parameters.AddWithValue("@Content", content);
update.Parameters.AddWithValue("@MetadataId", metadataId);
await update.ExecuteNonQueryAsync(token).ConfigureAwait(false);
await update.ExecuteNonQueryAsync(true, token).ConfigureAwait(false);
}
public override void Dispose()
@@ -143,7 +143,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@CurrentFilesetId", filesetid)
.SetParameterValue("@PreviousFilesetId", prevFilesetId);
await cmd.ExecuteNonQueryAsync(token).ConfigureAwait(false);
await cmd.ExecuteNonQueryAsync(true, token).ConfigureAwait(false);
}
/// <summary>
@@ -220,7 +220,7 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_rtr)
.SetParameterValue("@FilesetId", filesetid);
return await cmd.ExecuteNonQueryAsync(token).ConfigureAwait(false);
return await cmd.ExecuteNonQueryAsync(true, token).ConfigureAwait(false);
}
/// <summary>
@@ -480,7 +480,7 @@ namespace Duplicati.Library.Main.Database
")
.SetParameterValue("@Name", volumename);
var blockCount = await cmd.ExecuteNonQueryAsync(token)
var blockCount = await cmd.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (blockCount == 0)
@@ -561,7 +561,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.SetParameterValue("@PreviousRestoredValue", 0)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false) == 1;
if (restored)
@@ -569,14 +569,14 @@ namespace Duplicati.Library.Main.Database
await m_copyIntoDuplicatedBlocks.SetTransaction(m_rtr)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
var c = await m_assignBlocksToNewVolume.SetTransaction(m_rtr)
.SetParameterValue("@TargetVolumeId", targetVolumeId)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != 1)
@@ -709,7 +709,7 @@ namespace Duplicati.Library.Main.Database
")
.SetParameterValue("@HashesPerBlock", hashesPerBlock)
.SetParameterValue("@Restored", 0)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
cmd.SetCommandAndParameters($@"
@@ -816,7 +816,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@SourceVolumeId", sourceVolumeId)
.SetParameterValue("@Restored", 1);
var moved = await cmd.ExecuteNonQueryAsync(token)
var moved = await cmd.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Then update the blocks table to point to the new volume
@@ -836,7 +836,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@TargetVolumeId", targetVolumeId)
.SetParameterValue("@SourceVolumeId", sourceVolumeId)
.SetParameterValue("@Restored", 1)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (updated != moved)
@@ -1070,7 +1070,7 @@ namespace Duplicati.Library.Main.Database
await c2
.SetParameterValue("@MetadataId", rd.GetValue(0))
.SetParameterValue("@BlocksetId", rd.GetValue(1))
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
}
@@ -1127,7 +1127,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Path", rd.GetValue(1))
.SetParameterValue("@BlocksetId", rd.GetValue(2))
.SetParameterValue("@MetadataId", rd.GetValue(3))
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
}
@@ -1270,7 +1270,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Path", rd.GetValue(2))
.SetParameterValue("@BlocksetId", rd.GetValue(3))
.SetParameterValue("@MetadataId", rd.GetValue(4))
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
}
@@ -1484,7 +1484,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""BlocksetID"" = @BlocksetId
")
.SetParameterValue("@BlocksetId", blocksetid)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
c2.SetCommandAndParameters(@"
@@ -1530,7 +1530,7 @@ namespace Duplicati.Library.Main.Database
{
var rc = await c6
.SetParameterValue("@DeletedBlockId", deletedBlockId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (rc != 2)
@@ -1542,7 +1542,7 @@ namespace Duplicati.Library.Main.Database
await c3.SetParameterValue("@BlocksetId", blocksetid)
.SetParameterValue("@Index", ix)
.SetParameterValue("@Hash", blkey)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
ix++;
@@ -1582,7 +1582,7 @@ namespace Duplicati.Library.Main.Database
{
var rc = await c6
.SetParameterValue("@DeletedBlockId", deletedBlockId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (rc != 2)
throw new Exception($"Unexpected update count: {rc}");
@@ -1594,7 +1594,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@BlocksetId", blocksetid)
.SetParameterValue("@Index", ix)
.SetParameterValue("@Hash", blkeyfinal)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
}
@@ -1684,7 +1684,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@BlocksetId", rd.GetValue(0))
.SetParameterValue("@Index", rd.GetValue(1))
.SetParameterValue("@Limit", expected)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (actual != expected)
@@ -1762,7 +1762,7 @@ namespace Duplicati.Library.Main.Database
await cmd
.SetParameterValue("@Hash", kp.Key)
.SetParameterValue("@Size", kp.Value)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -2014,7 +2014,7 @@ namespace Duplicati.Library.Main.Database
AND ""m"".""BlocksetID"" != @KeepBlockset
")
.SetParameterValue("@KeepBlockset", emptyBlocksetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Step 2: Update FileLookup to use a valid metadata ID
@@ -2032,7 +2032,7 @@ namespace Duplicati.Library.Main.Database
)
")
.SetParameterValue("@KeepBlockset", emptyBlocksetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Step 3: Delete obsolete Metadataset entries
@@ -2043,7 +2043,7 @@ namespace Duplicati.Library.Main.Database
FROM ""{tablename}""
)
")
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Step 4: Delete orphaned blocksets (affected only)
@@ -2065,7 +2065,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""BlocksetID"" = ""Blockset"".""ID""
)
")
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Step 5: Confirm all broken metadata entries are resolved
@@ -2093,7 +2093,7 @@ namespace Duplicati.Library.Main.Database
try
{
await cmd.SetCommandAndParameters($@"DROP TABLE IF EXISTS ""{tablename}"" ")
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
catch (Exception ex)
@@ -509,7 +509,7 @@ namespace Duplicati.Library.Main.Database
AND ""FilesetEntry"".""FilesetID"" = @FilesetId
")
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
else if (Library.Utility.Utility.IsFSCaseSensitive && filter is FilterExpression expression && expression.Type == FilterType.Simple)
@@ -536,13 +536,14 @@ namespace Duplicati.Library.Main.Database
")
.ConfigureAwait(false);
foreach (var s in p)
{
await cmd
.SetParameterValue("@Path", s)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
using (new Logging.Timer(LOGTAG, "InsertFilteredPaths", "Inserting filtered paths into temporary table"))
foreach (var s in p)
{
await cmd
.SetParameterValue("@Path", s)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
var c = await cmd.SetCommandAndParameters($@"
INSERT INTO ""{m_tempfiletable}"" (
@@ -570,7 +571,7 @@ namespace Duplicati.Library.Main.Database
)
")
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (c != p.Length && c != 0)
@@ -647,21 +648,25 @@ namespace Duplicati.Library.Main.Database
0
)
");
await using var rd = await cmd.ExecuteReaderAsync(token)
.ConfigureAwait(false);
while (await rd.ReadAsync(token).ConfigureAwait(false))
using (new Logging.Timer(LOGTAG, "ApplyFilter", "Iterating files with filter"))
{
rd.GetValues(values);
var path = values[1] as string;
if (path != null && FilterExpression.Matches(filter, path.ToString()!))
await using var rd = await cmd.ExecuteReaderAsync(token)
.ConfigureAwait(false);
while (await rd.ReadAsync(token).ConfigureAwait(false))
{
await cmd2
.SetParameterValue("@ID", values[0])
.SetParameterValue("@Path", values[1])
.SetParameterValue("@BlocksetID", values[2])
.SetParameterValue("@MetadataID", values[3])
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
rd.GetValues(values);
var path = values[1] as string;
if (path != null && FilterExpression.Matches(filter, path.ToString()!))
{
await cmd2
.SetParameterValue("@ID", values[0])
.SetParameterValue("@Path", values[1])
.SetParameterValue("@BlocksetID", values[2])
.SetParameterValue("@MetadataID", values[3])
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
}
}
}
@@ -734,7 +739,7 @@ namespace Duplicati.Library.Main.Database
")
.SetTransaction(m_rtr);
var v0 = await cmd.ExecuteScalarAsync(token).ConfigureAwait(false);
var v0 = await cmd.ExecuteScalarAsync(true, token).ConfigureAwait(false);
if (v0 == null || v0 == DBNull.Value)
return null;
@@ -756,7 +761,7 @@ namespace Duplicati.Library.Main.Database
")
.SetTransaction(m_rtr);
var v0 = await cmd.ExecuteScalarAsync(token).ConfigureAwait(false);
var v0 = await cmd.ExecuteScalarAsync(true, token).ConfigureAwait(false);
var maxpath = "";
if (v0 != null && v0 != DBNull.Value)
maxpath = v0.ToString()!;
@@ -863,7 +868,7 @@ namespace Duplicati.Library.Main.Database
END
")
.SetParameterValue("@Path", Util.AppendDirSeparator(System.IO.Path.GetPathRoot(Library.Utility.TempFolder.SystemTempPath) ?? "").Replace("\\", "/"))
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
else
@@ -914,7 +919,7 @@ namespace Duplicati.Library.Main.Database
SET ""TargetPath"" = SUBSTR(""Path"", @PrefixLength)
")
.SetParameterValue("@PrefixLength", largest_prefix.Length + 1)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
}
@@ -944,7 +949,7 @@ namespace Duplicati.Library.Main.Database
SET ""TargetPath"" = @Destination || ""TargetPath""
")
.SetParameterValue("@Destination", Util.AppendDirSeparator(destination))
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -1068,7 +1073,7 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_rtr)
.SetParameterValue("@TargetPath", newname)
.SetParameterValue("@ID", ID)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
await m_rtr.CommitAsync(token: token).ConfigureAwait(false);
@@ -1702,13 +1707,15 @@ namespace Duplicati.Library.Main.Database
@Size
)
");
foreach (var s in curvolume.Blocks)
{
await c.SetParameterValue("@Hash", s.Key)
.SetParameterValue("@Size", s.Value)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
using (new Logging.Timer(LOGTAG, "InsertBlocks", "Inserting blocks from current volume"))
foreach (var s in curvolume.Blocks)
{
await c.SetParameterValue("@Hash", s.Key)
.SetParameterValue("@Size", s.Value)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
// The index _HashSizeIndex is not needed anymore. Index on "Blocks-..." is used on Join in GetMissingBlocks
@@ -2251,7 +2258,7 @@ namespace Duplicati.Library.Main.Database
")
.SetTransaction(m_rtr);
var result = await cmd.ExecuteScalarAsync(token)
var result = await cmd.ExecuteScalarAsync(true, token)
.ConfigureAwait(false);
if (result == DBNull.Value || result == null)
@@ -2598,7 +2605,7 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_db.Transaction)
.SetParameterValue("@TargetFileId", targetfileid);
var r = await m_resetfileCommand.ExecuteNonQueryAsync(token)
var r = await m_resetfileCommand.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (r <= 0)
throw new Exception("Unexpected reset result");
@@ -2614,7 +2621,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Metadata", includeMetadata ? 1 : 0);
var r = await m_updateAsRestoredCommand
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (r <= 0)
throw new Exception("Unexpected reset result");
@@ -2629,7 +2636,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@TargetFileId", targetfileid);
var r = await m_updateFileAsDataVerifiedCommand
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (r != 1)
throw new Exception("Unexpected result when marking file as verified.");
@@ -2648,7 +2655,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Metadata", metadata);
var r = await m_insertblockCommand
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
if (r != 1)
@@ -2887,21 +2894,25 @@ namespace Duplicati.Library.Main.Database
SELECT DISTINCT ""{m_tempfiletable}"".""Path""
FROM ""{m_tempfiletable}""
");
await using (var rd = await cmdReader.ExecuteReaderAsync(token).ConfigureAwait(false))
using (new Logging.Timer(LOGTAG, "CheckLocalSourceExists", "Checking if local source files exist"))
{
while (await rd.ReadAsync(token).ConfigureAwait(false))
await using (var rd = await cmdReader.ExecuteReaderAsync(token).ConfigureAwait(false))
{
var sourcepath = rd.ConvertValueToString(0);
if (SystemIO.IO_OS.FileExists(sourcepath))
while (await rd.ReadAsync(token).ConfigureAwait(false))
{
await cmd
.SetParameterValue("@Path", sourcepath)
.ExecuteNonQueryAsync(token)
.ConfigureAwait(false);
}
else
{
Logging.Log.WriteVerboseMessage(LOGTAG, "LocalSourceMissing", "Local source file not found: {0}", sourcepath);
var sourcepath = rd.ConvertValueToString(0);
if (SystemIO.IO_OS.FileExists(sourcepath))
{
await cmd
.SetParameterValue("@Path", sourcepath)
.ExecuteNonQueryAsync(token) // Not logging as we log the total time
.ConfigureAwait(false);
}
else
{
Logging.Log.WriteVerboseMessage(LOGTAG, "LocalSourceMissing", "Local source file not found: {0}", sourcepath);
}
}
}
}
@@ -100,7 +100,7 @@ namespace Duplicati.Library.Main.Database
WHERE ""Name"" = @Name
")
.SetParameterValue("@Name", name)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -556,7 +556,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Metasize", metasize)
.SetParameterValue("@Metahash", metahash)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -646,7 +646,7 @@ namespace Duplicati.Library.Main.Database
await cmd
.SetCommandAndParameters(create)
.SetParameterValue("@Name", m_volumename)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
cmd
@@ -775,7 +775,7 @@ namespace Duplicati.Library.Main.Database
.SetParameterValue("@Name", filename)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", length)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -844,7 +844,7 @@ namespace Duplicati.Library.Main.Database
await cmd
.SetCommandAndParameters(create)
.SetParameterValue("@Name", m_volumename)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
cmd
@@ -980,7 +980,7 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_db.Transaction)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -1083,7 +1083,7 @@ namespace Duplicati.Library.Main.Database
await cmd
.SetCommandAndParameters(create)
.SetParameterValue("@Name", m_volumename)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
cmd
@@ -1181,7 +1181,7 @@ namespace Duplicati.Library.Main.Database
.SetTransaction(m_db.Transaction)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
}
@@ -1303,7 +1303,7 @@ namespace Duplicati.Library.Main.Database
await cmd
.SetCommandAndParameters(create)
.SetParameterValue("@Name", m_volumename)
.ExecuteNonQueryAsync(token)
.ExecuteNonQueryAsync(true, token)
.ConfigureAwait(false);
// Compare against actual values inserted into temp table
@@ -146,23 +146,25 @@ namespace Duplicati.Library.Main.Operation
if (!await m_result.TaskControl.ProgressRendevouz().ConfigureAwait(false))
return;
using (new Logging.Timer(LOGTAG, "InsertBaseFiles", "Inserting base files into database"))
using (var tmpfile = await backendManager.GetAsync(baseFile.File.Name, null, baseFile.File.Size, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var rd = new Volumes.FilesetVolumeReader(RestoreHandler.GetCompressionModule(baseFile.File.Name), tmpfile, m_options))
foreach (var f in rd.Files)
if (FilterExpression.Matches(filter, f.Path))
await storageKeeper
.AddElement(f.Path, f.Hash, f.Metahash, f.Size, conv(f.Type), false, m_result.TaskControl.ProgressToken)
.AddElement(f.Path, f.Hash, f.Metahash, f.Size, conv(f.Type), false, false, m_result.TaskControl.ProgressToken)
.ConfigureAwait(false);
if (!await m_result.TaskControl.ProgressRendevouz().ConfigureAwait(false))
return;
using (new Logging.Timer(LOGTAG, "InsertCompareFiles", "Inserting compare files into database"))
using (var tmpfile = await backendManager.GetAsync(compareFile.File.Name, null, compareFile.File.Size, m_result.TaskControl.ProgressToken).ConfigureAwait(false))
using (var rd = new Volumes.FilesetVolumeReader(RestoreHandler.GetCompressionModule(compareFile.File.Name), tmpfile, m_options))
foreach (var f in rd.Files)
if (FilterExpression.Matches(filter, f.Path))
await storageKeeper
.AddElement(f.Path, f.Hash, f.Metahash, f.Size, conv(f.Type), true, m_result.TaskControl.ProgressToken)
.AddElement(f.Path, f.Hash, f.Metahash, f.Size, conv(f.Type), true, false, m_result.TaskControl.ProgressToken)
.ConfigureAwait(false);
}