using System; using System.Data; #nullable enable namespace Duplicati.Library.Main.Database; /// /// Wraps a transaction so it can be comitted and restarted /// internal class ReusableTransaction : IDisposable { /// /// The tag used for logging /// private static readonly string LOGTAG = Logging.Log.LogTagFromType(typeof(LocalDatabase)); /// /// The database to use /// private readonly LocalDatabase m_db; /// /// The current transaction /// private IDbTransaction? m_transaction; /// /// Creates a new reusable transaction /// /// The database to use public ReusableTransaction(LocalDatabase db, IDbTransaction? transaction = null) { m_db = db; m_transaction = transaction ?? db.BeginTransaction(); } /// /// The current transaction /// public IDbTransaction Transaction => m_transaction ?? throw new InvalidOperationException("Transaction is disposed"); /// /// Commits the current transaction and optionally restarts it /// /// The log message to use /// True if the transaction should be restarted public void Commit(string? message = null, bool restart = true) { if (m_transaction == null) throw new InvalidOperationException("Transaction is already disposed"); if (m_transaction != null) { using (var timer = string.IsNullOrWhiteSpace(message) ? null : new Logging.Timer(LOGTAG, message, "CommitTransaction")) m_transaction.Commit(); m_transaction.Dispose(); m_transaction = null; } if (restart) m_transaction = m_db.BeginTransaction(); } /// public void Dispose() { m_transaction?.Dispose(); m_transaction = null; } }