From 7f736166149ba53f11ab0231a05d8faf5fd5eb97 Mon Sep 17 00:00:00 2001 From: BlueBlock Date: Sat, 7 Sep 2019 17:16:34 -0400 Subject: [PATCH] add purging of deleted remote volumes --- .../Library/Main/Database/LocalDatabase.cs | 56 +++++++++++++++---- .../Library/Main/Operation/BackupHandler.cs | 2 + 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Duplicati/Library/Main/Database/LocalDatabase.cs b/Duplicati/Library/Main/Database/LocalDatabase.cs index 0f76f8f8d..723899495 100644 --- a/Duplicati/Library/Main/Database/LocalDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalDatabase.cs @@ -22,6 +22,7 @@ namespace Duplicati.Library.Main.Database private readonly System.Data.IDbCommand m_selectremotevolumesCommand; private readonly System.Data.IDbCommand m_selectremotevolumeCommand; private readonly System.Data.IDbCommand m_removeremotevolumeCommand; + private readonly System.Data.IDbCommand m_removedeletedremotevolumeCommand; private readonly System.Data.IDbCommand m_selectremotevolumeIdCommand; private readonly System.Data.IDbCommand m_createremotevolumeCommand; private readonly System.Data.IDbCommand m_selectduplicateRemoteVolumesCommand; @@ -108,6 +109,7 @@ namespace Duplicati.Library.Main.Database m_insertlogCommand = connection.CreateCommand(); m_insertremotelogCommand = connection.CreateCommand(); m_removeremotevolumeCommand = connection.CreateCommand(); + m_removedeletedremotevolumeCommand = connection.CreateCommand(); m_selectremotevolumeIdCommand = connection.CreateCommand(); m_createremotevolumeCommand = connection.CreateCommand(); m_insertIndexBlockLink = connection.CreateCommand(); @@ -133,6 +135,9 @@ namespace Duplicati.Library.Main.Database m_removeremotevolumeCommand.CommandText = @"DELETE FROM ""Remotevolume"" WHERE ""Name"" = ? AND (""DeleteGraceTime"" < ? OR ""State"" != ?)"; m_removeremotevolumeCommand.AddParameters(3); + m_removedeletedremotevolumeCommand.CommandText = $@"DELETE FROM ""Remotevolume"" WHERE ""DeleteGraceTime"" < ? AND ""State"" == ""{RemoteVolumeState.Deleted.ToString()}"""; + m_removedeletedremotevolumeCommand.AddParameter(); + m_selectremotevolumeIdCommand.CommandText = @"SELECT ""ID"" FROM ""Remotevolume"" WHERE ""Name"" = ?"; m_createremotevolumeCommand.CommandText = @"INSERT INTO ""Remotevolume"" (""OperationID"", ""Name"", ""Type"", ""State"", ""Size"", ""VerificationCount"", ""DeleteGraceTime"") VALUES (?, ?, ?, ?, ?, ?, ?); SELECT last_insert_rowid();"; @@ -179,18 +184,32 @@ namespace Duplicati.Library.Main.Database m_updateremotevolumeCommand.SetParameterValue(2, hash); m_updateremotevolumeCommand.SetParameterValue(3, size); m_updateremotevolumeCommand.SetParameterValue(4, name); + var c = m_updateremotevolumeCommand.ExecuteNonQuery(); + if (c != 1) - throw new Exception(string.Format("Unexpected number of remote volumes detected: {0}!", c)); + { + throw new Exception($"Unexpected number of remote volumes detected: {c}!"); + } if (deleteGraceTime.Ticks > 0) - using(var cmd = m_connection.CreateCommand(transaction)) - if ((c = cmd.ExecuteNonQuery(@"UPDATE ""RemoteVolume"" SET ""DeleteGraceTime"" = ? WHERE ""Name"" = ? ", (DateTime.UtcNow + deleteGraceTime).Ticks, name)) != 1) - throw new Exception(string.Format("Unexpected number of updates when recording remote volume updates: {0}!", c)); - + { + using (var cmd = m_connection.CreateCommand(transaction)) + { + if ((c = cmd.ExecuteNonQuery( + @"UPDATE ""RemoteVolume"" SET ""DeleteGraceTime"" = ? WHERE ""Name"" = ? ", + Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(DateTime.UtcNow + deleteGraceTime), + name)) != 1) + { + throw new Exception($"Unexpected number of updates when recording remote volume updates: {c}!"); + } + } + } if (!suppressCleanup && state == RemoteVolumeState.Deleted) - RemoveRemoteVolume(name, transaction); + { + RemoveRemoteVolume(name, transaction); + } } public IEnumerable> FilesetTimes @@ -436,14 +455,15 @@ namespace Duplicati.Library.Main.Database } catch { /* Ignore, will be deleted on close anyway. */ } - m_removeremotevolumeCommand.Transaction = tr.Parent; - m_removeremotevolumeCommand.SetParameterValue(1, DateTime.UtcNow.Ticks); - m_removeremotevolumeCommand.SetParameterValue(2, RemoteVolumeState.Deleted.ToString()); - foreach (var name in names) + m_removeremotevolumeCommand.Transaction = tr.Parent; + m_removeremotevolumeCommand.SetParameterValue(1, Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(DateTime.UtcNow)); + m_removeremotevolumeCommand.SetParameterValue(2, RemoteVolumeState.Deleted.ToString()); + foreach (var name in names) { m_removeremotevolumeCommand.SetParameterValue(0, name); m_removeremotevolumeCommand.ExecuteNonQuery(); } + tr.Commit(); } } @@ -1139,7 +1159,7 @@ ORDER BY } /// - /// Keeps a list of filenames in a temporary table with a single columne Path + /// Keeps a list of filenames in a temporary table with a single column Path /// public class FilteredFilenameTable : IDisposable { @@ -1331,7 +1351,19 @@ ORDER BY tr.Commit(); } } - + + public void PurgeDeletedVolumes(DateTime threshold) + { + using (var tr = m_connection.BeginTransaction()) + using (var cmd = m_connection.CreateCommand(tr)) + { + m_removedeletedremotevolumeCommand.Transaction = tr; + m_removedeletedremotevolumeCommand.SetParameterValue(0, Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(threshold)); + m_removedeletedremotevolumeCommand.ExecuteNonQuery(); + tr.Commit(); + } + } + public virtual void Dispose() { if (IsDisposed) diff --git a/Duplicati/Library/Main/Operation/BackupHandler.cs b/Duplicati/Library/Main/Operation/BackupHandler.cs index debbda20a..752981236 100644 --- a/Duplicati/Library/Main/Operation/BackupHandler.cs +++ b/Duplicati/Library/Main/Operation/BackupHandler.cs @@ -534,6 +534,8 @@ namespace Duplicati.Library.Main.Operation m_database.WriteResults(); m_database.PurgeLogData(m_options.LogRetention); + m_database.PurgeDeletedVolumes(DateTime.UtcNow); + if (m_options.AutoVacuum) { m_result.VacuumResults = new VacuumResults(m_result);