Fix remote file locking on Windows
This fixes a locked database issue on Windows. The issue was caused by the backup process having an open database, and then not passing that connection to the lock handler. The lock handler would then attempt to open a new connection to the same database, which would fail. This PR fixes the issue by passing an instance of the database to the lock handler. Also addressed a logic issue where the dbpath was checked, even if an existing database connection was found. Also fixed the lock results not setting the EndTime property, causing the reported lelapsed time to be off.
This commit is contained in:
@@ -54,6 +54,23 @@ namespace Duplicati.Library.Main.Database
|
||||
return dbnew;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="LocalLockDatabase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="database">The database to create the new instance on.</param>
|
||||
/// <param name="token">A cancellation token to cancel the operation.</param>
|
||||
/// <returns>The <see cref="LocalLockDatabase"/> instance</returns>
|
||||
public static async Task<LocalLockDatabase> CreateAsync(LocalDatabase database, CancellationToken token)
|
||||
{
|
||||
var db = (LocalLockDatabase)await LocalDatabase.CreateLocalDatabaseAsync(
|
||||
database,
|
||||
new LocalLockDatabase(),
|
||||
token
|
||||
).ConfigureAwait(false);
|
||||
db.ShouldCloseConnection = false;
|
||||
return db;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the lock expiration time for a remote volume.
|
||||
/// </summary>
|
||||
|
||||
@@ -604,9 +604,10 @@ namespace Duplicati.Library.Main.Operation
|
||||
return;
|
||||
}
|
||||
|
||||
m_result.LockResults = new SetLockResults(m_result);
|
||||
using var lockDb = await LocalLockDatabase.CreateAsync(m_database, m_taskReader.StopToken);
|
||||
m_result.LockResults ??= new SetLockResults();
|
||||
await new SetLocksHandler(m_options, (SetLockResults)m_result.LockResults)
|
||||
.RunAsync(backendManager, versionTimestamps)
|
||||
.RunAsync(backendManager, lockDb, versionTimestamps)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,14 +73,14 @@ namespace Duplicati.Library.Main.Operation
|
||||
if (!backendManager.SupportsObjectLocking)
|
||||
throw new UserInformationException("Backend does not support object locking", "BackendDoesNotSupportLocking");
|
||||
|
||||
if (!File.Exists(m_options.Dbpath))
|
||||
var ownsDatabase = databaseOverride is null;
|
||||
if (ownsDatabase && !File.Exists(m_options.Dbpath))
|
||||
throw new UserInformationException(string.Format("Database file does not exist: {0}", m_options.Dbpath), "DatabaseFileDoesNotExist");
|
||||
|
||||
m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.ReadLockInfo_Running);
|
||||
|
||||
var ownsDatabase = databaseOverride is null;
|
||||
await using var db = ownsDatabase
|
||||
? await LocalLockDatabase.CreateAsync(m_options.Dbpath, null, m_result.TaskControl.ProgressToken).ConfigureAwait(false)
|
||||
? await LocalLockDatabase.CreateAsync(m_options.Dbpath!, null, m_result.TaskControl.ProgressToken).ConfigureAwait(false)
|
||||
: null;
|
||||
var database = databaseOverride ?? db!;
|
||||
|
||||
@@ -118,6 +118,7 @@ namespace Duplicati.Library.Main.Operation
|
||||
|
||||
m_result.VolumesRead = readCount;
|
||||
m_result.VolumesUpdated = updatedCount;
|
||||
m_result.EndTime = DateTime.UtcNow;
|
||||
|
||||
if (updatedCount > 0 || errorCount > 0)
|
||||
Log.WriteInformationMessage(LOGTAG, "ReadLockInfoComplete", "Read lock info complete: {0} updated, {1} errors", updatedCount, errorCount);
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Duplicati.Library.Main.Operation
|
||||
public Task RunAsync(IBackendManager backendManager, IEnumerable<DateTime>? versionTimestamps = null)
|
||||
=> RunAsync(backendManager, null, versionTimestamps);
|
||||
|
||||
internal async Task RunAsync(IBackendManager backendManager, Database.LocalLockDatabase? databaseOverride, IEnumerable<DateTime>? versionTimestamps = null)
|
||||
public async Task RunAsync(IBackendManager backendManager, Database.LocalLockDatabase? databaseOverride, IEnumerable<DateTime>? versionTimestamps = null)
|
||||
{
|
||||
if (m_options.RemoteFileLockDuration is null)
|
||||
throw new UserInformationException("No lock duration specified", "MissingLockDuration");
|
||||
@@ -61,16 +61,16 @@ namespace Duplicati.Library.Main.Operation
|
||||
if (!backendManager.SupportsObjectLocking)
|
||||
throw new UserInformationException("Backend does not support object locking", "BackendDoesNotSupportLocking");
|
||||
|
||||
if (!File.Exists(m_options.Dbpath))
|
||||
var ownsDatabase = databaseOverride is null;
|
||||
if (ownsDatabase && !File.Exists(m_options.Dbpath))
|
||||
throw new Exception(string.Format("Database file does not exist: {0}", m_options.Dbpath));
|
||||
|
||||
var effectiveVersionTimestamps = versionTimestamps ?? m_versionTimestamps;
|
||||
|
||||
m_result.OperationProgressUpdater.UpdatePhase(OperationPhase.Backup_Lock);
|
||||
|
||||
var ownsDatabase = databaseOverride is null;
|
||||
await using var db = ownsDatabase
|
||||
? await LocalLockDatabase.CreateAsync(m_options.Dbpath, null, m_result.TaskControl.ProgressToken).ConfigureAwait(false)
|
||||
? await LocalLockDatabase.CreateAsync(m_options.Dbpath!, null, m_result.TaskControl.ProgressToken).ConfigureAwait(false)
|
||||
: null;
|
||||
var database = databaseOverride ?? db!;
|
||||
|
||||
@@ -123,6 +123,7 @@ namespace Duplicati.Library.Main.Operation
|
||||
|
||||
m_result.VolumesRead = readCount;
|
||||
m_result.VolumesUpdated = updatedCount;
|
||||
m_result.EndTime = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
private async Task<List<long>> ResolveFilesetIdsAsync(Database.LocalListDatabase db, IEnumerable<DateTime>? suppliedVersions)
|
||||
|
||||
Reference in New Issue
Block a user