1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-16 07:22:55 +08:00

Fix rollback logic not necessrily cleaning up file store

This commit is contained in:
Dean Herbert 2019-06-10 16:14:42 +09:00
parent fae32b3901
commit 02b376d962

View File

@ -154,25 +154,22 @@ namespace osu.Game.Database
await Task.WhenAll(paths.Select(path => Import(path, notification.CancellationToken).ContinueWith(t => await Task.WhenAll(paths.Select(path => Import(path, notification.CancellationToken).ContinueWith(t =>
{ {
if (notification.CancellationToken.IsCancellationRequested) notification.CancellationToken.ThrowIfCancellationRequested();
return;
lock (notification) lock (imported)
{ {
current++; Interlocked.Increment(ref current);
notification.Text = $"Imported {current} of {paths.Length} {term}s"; if (t.Exception == null)
notification.Progress = (float)current / paths.Length; {
}
if (t.Exception == null)
{
lock (imported)
imported.Add(t.Result); imported.Add(t.Result);
} notification.Text = $"Imported {current} of {paths.Length} {term}s";
else notification.Progress = (float)current / paths.Length;
{ }
Logger.Error(t.Exception, $@"Could not import ({Path.GetFileName(path)})"); else
{
Logger.Error(t.Exception, $@"Could not import ({Path.GetFileName(path)})");
}
} }
}, TaskContinuationOptions.NotOnCanceled))); }, TaskContinuationOptions.NotOnCanceled)));
@ -300,23 +297,23 @@ namespace osu.Game.Database
delayEvents(); delayEvents();
void rollback()
{
if (!Delete(item))
{
// We may have not yet added the model to the underlying table, but should still clean up files.
Logger.Log($"Dereferencing files for incomplete import of {item}.", LoggingTarget.Database);
Files.Dereference(item.Files.Select(f => f.FileInfo).ToArray());
}
}
try try
{ {
Logger.Log($"Importing {item}...", LoggingTarget.Database); Logger.Log($"Importing {item}...", LoggingTarget.Database);
item.Files = archive != null ? createFileInfos(archive, Files) : new List<TFileModel>(); item.Files = archive != null ? createFileInfos(archive, Files) : new List<TFileModel>();
var localItem = item; await Populate(item, archive, cancellationToken);
try
{
await Populate(item, archive, cancellationToken);
}
catch (Exception)
{
if (!Delete(localItem))
Files.Dereference(localItem.Files.Select(f => f.FileInfo).ToArray());
}
using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes.
{ {
@ -333,6 +330,8 @@ namespace osu.Game.Database
Undelete(existing); Undelete(existing);
Logger.Log($"Found existing {nameof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); Logger.Log($"Found existing {nameof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database);
handleEvent(() => ItemAdded?.Invoke(existing, true)); handleEvent(() => ItemAdded?.Invoke(existing, true));
rollback();
return existing; return existing;
} }
else else
@ -349,9 +348,6 @@ namespace osu.Game.Database
} }
catch (Exception e) catch (Exception e)
{ {
if (!Delete(item))
Files.Dereference(item.Files.Select(f => f.FileInfo).ToArray());
write.Errors.Add(e); write.Errors.Add(e);
throw; throw;
} }
@ -359,13 +355,12 @@ namespace osu.Game.Database
Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database); Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database);
} }
catch (TaskCanceledException)
{
throw;
}
catch (Exception e) catch (Exception e)
{ {
Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); if (!(e is TaskCanceledException))
Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database);
rollback();
item = null; item = null;
} }
finally finally