Slight bundle & fileutil refactor: (#524)
- Actually load the bundle cache file now - Don't read file as string with StreamReader, instead read with ReadAllTextAsync - Slight refactor to bundle hashing Co-authored-by: Chomp <27521899+chompDev@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using SPTarkov.Server.Core.Loaders;
|
||||
using SPTarkov.Server.Core.Models.Common;
|
||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||
using SPTarkov.Server.Core.Routers.Serializers;
|
||||
using SPTarkov.Server.Core.Utils;
|
||||
|
||||
namespace SPTarkov.Server.Core.Callbacks;
|
||||
@@ -19,9 +20,10 @@ public class BundleCallbacks(HttpResponseUtil httpResponseUtil, BundleLoader bun
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: what does it do
|
||||
/// Handle requests to /files/bundle <br/>
|
||||
/// <br/>
|
||||
/// Makes sure the output is set to BUNDLE so that the BundleSerializer's <see cref="BundleSerializer.CanHandle"/> can handle it.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ValueTask<string> GetBundle(string url, object info, MongoId sessionID)
|
||||
{
|
||||
return new ValueTask<string>("BUNDLE");
|
||||
|
||||
@@ -39,6 +39,8 @@ public class BundleLoader(ISptLogger<BundleLoader> logger, JsonUtil jsonUtil, Bu
|
||||
|
||||
public async Task LoadBundlesAsync(SptMod mod)
|
||||
{
|
||||
await bundleHashCacheService.HydrateCache();
|
||||
|
||||
var modPath = mod.GetModPath();
|
||||
|
||||
var modBundles = await jsonUtil.DeserializeFromFileAsync<BundleManifest>(
|
||||
@@ -59,12 +61,7 @@ public class BundleLoader(ISptLogger<BundleLoader> logger, JsonUtil jsonUtil, Bu
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!bundleHashCacheService.CalculateAndMatchHash(bundleLocalPath))
|
||||
{
|
||||
await bundleHashCacheService.CalculateAndStoreHash(bundleLocalPath);
|
||||
}
|
||||
|
||||
var bundleHash = bundleHashCacheService.GetStoredValue(bundleLocalPath);
|
||||
var bundleHash = await bundleHashCacheService.CalculateMatchAndStoreHash(bundleLocalPath);
|
||||
|
||||
AddBundle(bundleManifest.Key, new BundleInfo(relativeModPath, bundleManifest, bundleHash));
|
||||
}
|
||||
|
||||
@@ -9,9 +9,27 @@ public class BundleHashCacheService(ISptLogger<BundleHashCacheService> logger, J
|
||||
{
|
||||
protected const string _bundleHashCachePath = "./user/cache/";
|
||||
protected const string _cacheName = "bundleHashCache.json";
|
||||
protected readonly Dictionary<string, uint> _bundleHashes = [];
|
||||
protected Dictionary<string, uint> _bundleHashes = [];
|
||||
|
||||
public uint GetStoredValue(string key)
|
||||
public async Task HydrateCache()
|
||||
{
|
||||
if (!Directory.Exists(_bundleHashCachePath))
|
||||
{
|
||||
Directory.CreateDirectory(_bundleHashCachePath);
|
||||
}
|
||||
|
||||
var fullCachePath = Path.Join(_bundleHashCachePath, _cacheName);
|
||||
|
||||
// File doesn't exist, assume this is the first time we're trying to load in bundles
|
||||
if (!File.Exists(fullCachePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_bundleHashes = await jsonUtil.DeserializeFromFileAsync<Dictionary<string, uint>>(fullCachePath) ?? [];
|
||||
}
|
||||
|
||||
protected uint GetStoredValue(string key)
|
||||
{
|
||||
if (!_bundleHashes.TryGetValue(key, out var value))
|
||||
{
|
||||
@@ -21,37 +39,44 @@ public class BundleHashCacheService(ISptLogger<BundleHashCacheService> logger, J
|
||||
return value;
|
||||
}
|
||||
|
||||
public async Task StoreValue(string bundlePath, uint hash)
|
||||
protected async Task StoreValue(string bundlePath, uint hash)
|
||||
{
|
||||
_bundleHashes.Add(bundlePath, hash);
|
||||
|
||||
if (!Directory.Exists(_bundleHashCachePath))
|
||||
var bundleHashesSerialized = jsonUtil.Serialize(_bundleHashes);
|
||||
|
||||
if (bundleHashesSerialized is null)
|
||||
{
|
||||
Directory.CreateDirectory(_bundleHashCachePath);
|
||||
return;
|
||||
}
|
||||
|
||||
await fileUtil.WriteFileAsync(Path.Join(_bundleHashCachePath, _cacheName), jsonUtil.Serialize(_bundleHashes));
|
||||
await fileUtil.WriteFileAsync(Path.Join(_bundleHashCachePath, _cacheName), bundleHashesSerialized);
|
||||
|
||||
logger.Debug($"Bundle: {bundlePath} hash stored in: ${_bundleHashCachePath}");
|
||||
}
|
||||
|
||||
public bool CalculateAndMatchHash(string BundlePath)
|
||||
/// <summary>
|
||||
/// Calculate, match the current hash and store the correct hash of the bundle
|
||||
/// </summary>
|
||||
/// <param name="BundlePath">The path to the bundle</param>
|
||||
public async Task<uint> CalculateMatchAndStoreHash(string BundlePath)
|
||||
{
|
||||
return MatchWithStoredHash(BundlePath, CalculateHash(BundlePath));
|
||||
var hash = await CalculateHash(BundlePath);
|
||||
|
||||
if (!MatchWithStoredHash(BundlePath, hash))
|
||||
{
|
||||
await StoreValue(BundlePath, await CalculateHash(BundlePath));
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public async Task CalculateAndStoreHash(string BundlePath)
|
||||
protected async Task<uint> CalculateHash(string BundlePath)
|
||||
{
|
||||
await StoreValue(BundlePath, CalculateHash(BundlePath));
|
||||
return hashUtil.GenerateCrc32ForData(await fileUtil.ReadFileAsBytesAsync(BundlePath));
|
||||
}
|
||||
|
||||
public uint CalculateHash(string BundlePath)
|
||||
{
|
||||
var fileData = fileUtil.ReadFile(BundlePath);
|
||||
return hashUtil.GenerateCrc32ForData(fileData);
|
||||
}
|
||||
|
||||
public bool MatchWithStoredHash(string BundlePath, uint hash)
|
||||
protected bool MatchWithStoredHash(string BundlePath, uint hash)
|
||||
{
|
||||
return GetStoredValue(BundlePath) == hash;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Security.AccessControl;
|
||||
using SPTarkov.DI.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Utils;
|
||||
@@ -61,8 +62,17 @@ public class FileUtil
|
||||
|
||||
public string ReadFile(string path)
|
||||
{
|
||||
using var reader = new StreamReader(path);
|
||||
return reader.ReadToEnd();
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
public async Task<string> ReadFileAsync(string path)
|
||||
{
|
||||
return await File.ReadAllTextAsync(path);
|
||||
}
|
||||
|
||||
public async Task<byte[]> ReadFileAsBytesAsync(string path)
|
||||
{
|
||||
return await File.ReadAllBytesAsync(path);
|
||||
}
|
||||
|
||||
public void WriteFile(string filePath, string fileContent)
|
||||
|
||||
@@ -13,6 +13,11 @@ public class HashUtil(RandomUtil _randomUtil)
|
||||
return Crc32.HashToUInt32(new ArraySegment<byte>(Encoding.UTF8.GetBytes(data)));
|
||||
}
|
||||
|
||||
public uint GenerateCrc32ForData(ReadOnlySpan<byte> data)
|
||||
{
|
||||
return Crc32.HashToUInt32(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a hash for the data parameter
|
||||
/// </summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ public class SptServerBackgroundService(IReadOnlyList<SptMod> loadedMods, Bundle
|
||||
{
|
||||
foreach (var mod in loadedMods)
|
||||
{
|
||||
if (mod.ModMetadata?.IsBundleMod == true)
|
||||
if (mod.ModMetadata.IsBundleMod == true)
|
||||
{
|
||||
await bundleLoader.LoadBundlesAsync(mod);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user