Dispose of file handles in BSA creation, don't load unused patches.

This commit is contained in:
Timothy Baldridge 2021-01-15 07:00:58 -07:00
parent c8abca742a
commit a754d9ae68
5 changed files with 41 additions and 17 deletions

View File

@ -238,6 +238,7 @@ namespace Compression.BSA
await builder._dataSrc.CopyToAsync(ds);
}
await builder._dataSrc.DisposeAsync();
builder._dataSrc = slab.Allocate(ms.Length);
ms.Position = 0;
await ms.CopyToAsync(builder._dataSrc);

View File

@ -276,6 +276,8 @@ namespace Compression.BSA
{
await _srcData.CopyToWithStatusAsync(_srcData.Length, w, $"Compressing {_path}");
}
await _srcData.DisposeAsync();
_srcData = _bsa._slab.Allocate(r.Length);
r.Position = 0;
await r.CopyToWithStatusAsync(r.Length, _srcData, $"Writing {_path}");
@ -291,6 +293,8 @@ namespace Compression.BSA
w.IsStreamOwner = false;
await _srcData.CopyToWithStatusAsync(_srcData.Length, w, $"Compressing {_path}");
}
await _srcData.DisposeAsync();
_srcData = _bsa._slab.Allocate(r.Length);
r.Position = 0;
await r.CopyToWithStatusAsync(r.Length, _srcData, $"Writing {_path}");

View File

@ -26,7 +26,9 @@ namespace Wabbajack.Common
PatchSize BLOB,
Patch BLOB,
PRIMARY KEY (FromHash, ToHash))
WITHOUT ROWID";
WITHOUT ROWID;";
cmd.ExecuteNonQuery();
}
@ -82,10 +84,10 @@ namespace Wabbajack.Common
else
{
if (TryGetPatch(srcHash, destHash, out var array))
if (TryGetPatch(srcHash, destHash, out var entry))
{
await patchOutStream!.WriteAsync(array);
return array.Length;
await patchOutStream!.WriteAsync(await entry.GetData());
return entry.PatchSize;
}
}
@ -122,27 +124,43 @@ namespace Wabbajack.Common
return patchStream.Position;
}
public static bool TryGetPatch(Hash fromHash, Hash toHash, [MaybeNullWhen(false)] out byte[] array)
public static bool TryGetPatch(Hash fromHash, Hash toHash, [MaybeNullWhen(false)] out CacheEntry found)
{
using var cmd = new SQLiteCommand(_conn);
cmd.CommandText = @"SELECT PatchSize, Patch FROM PatchCache WHERE FromHash = @fromHash AND ToHash = @toHash";
cmd.CommandText = @"SELECT PatchSize FROM PatchCache WHERE FromHash = @fromHash AND ToHash = @toHash";
cmd.Parameters.AddWithValue("@fromHash", (long)fromHash);
cmd.Parameters.AddWithValue("@toHash", (long)toHash);
using var rdr = cmd.ExecuteReader();
while (rdr.Read())
{
array = new byte[rdr.GetInt64(0)];
rdr.GetBytes(1, 0, array, 0, array.Length);
found = new CacheEntry(fromHash, toHash, rdr.GetInt64(0));
return true;
}
array = Array.Empty<byte>();
found = default;
return false;
}
public record CacheEntry(Hash From, Hash To, long PatchSize)
{
public async Task<byte[]> GetData()
{
await using var cmd = new SQLiteCommand(_conn);
cmd.CommandText = @"SELECT PatchSize, Patch FROM PatchCache WHERE FromHash = @fromHash AND ToHash = @toHash";
cmd.Parameters.AddWithValue("@fromHash", (long)From);
cmd.Parameters.AddWithValue("@toHash", (long)To);
await using var rdr = await cmd.ExecuteReaderAsync();
while (await rdr.ReadAsync())
{
var array = new byte[rdr.GetInt64(0)];
rdr.GetBytes(1, 0, array, 0, array.Length);
return array;
}
return Array.Empty<byte>();
}
}
public static void VacuumDatabase()
@ -186,7 +204,7 @@ namespace Wabbajack.Common
public static Task<long> CreatePatchCached(Stream srcStream, Hash srcHash, Stream destStream, Hash destHash, Stream? patchOutStream = null) =>
PatchCache.CreatePatchCached(srcStream, srcHash, destStream, destHash, patchOutStream);
public static bool TryGetPatch(Hash foundHash, Hash fileHash, [MaybeNullWhen(false)] out byte[] ePatch) =>
public static bool TryGetPatch(Hash foundHash, Hash fileHash, [MaybeNullWhen(false)] out PatchCache.CacheEntry ePatch) =>
PatchCache.TryGetPatch(foundHash, fileHash, out ePatch);
}
}

View File

@ -430,7 +430,7 @@ namespace Wabbajack.Lib
pfa.FromFile = file;
pfa.FromHash = file.Hash;
pfa.ArchiveHashPath = file.MakeRelativePaths();
pfa.PatchID = await IncludeFile(bytes!);
pfa.PatchID = await IncludeFile(await bytes!.GetData());
}
});

View File

@ -110,7 +110,7 @@ namespace Wabbajack.Lib.CompilationSteps
var (_, bytes, file) = PickPatch(_compiler, patches);
e.FromHash = file.Hash;
e.ArchiveHashPath = file.MakeRelativePaths();
e.PatchID = await _compiler.IncludeFile(bytes!);
e.PatchID = await _compiler.IncludeFile(await bytes!.GetData());
}
else
{
@ -128,11 +128,11 @@ namespace Wabbajack.Lib.CompilationSteps
return e;
}
public static (bool, byte[], VirtualFile) PickPatch(ACompiler compiler, IEnumerable<(bool foundHash, byte[]? data, VirtualFile file)> patches)
public static (bool, PatchCache.CacheEntry, VirtualFile) PickPatch(ACompiler compiler, IEnumerable<(bool foundHash, PatchCache.CacheEntry? data, VirtualFile file)> patches)
{
var ordered = patches
.Select(f => (f.foundHash, f.data!, f.file))
.OrderBy(f => f.Item2.Length)
.OrderBy(f => f.Item2.PatchSize)
.ToArray();
var primaryChoice = ordered.FirstOrDefault(itm =>
@ -148,7 +148,8 @@ namespace Wabbajack.Lib.CompilationSteps
});
// If we didn't find a file from an archive or the primary game, use a secondary game file.
return primaryChoice != default ? primaryChoice : ordered.FirstOrDefault();
var result = primaryChoice != default ? primaryChoice : ordered.FirstOrDefault();
return result;
}
private AbsolutePath ModForFile(AbsolutePath file)