- tweak: Change content hold think

This commit is contained in:
2025-03-13 14:58:47 +03:00
parent fecaa266cf
commit 5384e97640
12 changed files with 82 additions and 85 deletions

View File

@@ -75,5 +75,5 @@ public sealed class FileApi : IReadWriteFileApi
return File.Exists(fullPath);
}
public IEnumerable<string> AllFiles => Directory.EnumerateFiles(RootPath, "*.*", SearchOption.AllDirectories);
public IEnumerable<string> AllFiles => Directory.EnumerateFiles(RootPath, "*.*", SearchOption.AllDirectories).Select(p=>p.Replace(RootPath,"").Substring(1));
}

View File

@@ -1,4 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Collections.Frozen;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using Nebula.Shared.FileApis.Interfaces;
using Nebula.Shared.Models;
using Robust.LoaderApi;
@@ -6,26 +9,59 @@ namespace Nebula.Shared.FileApis;
public class HashApi : IFileApi
{
private readonly IFileApi _fileApi;
public Dictionary<string, RobustManifestItem> Manifest;
private readonly IReadWriteFileApi _fileApi;
private readonly Dictionary<string, RobustManifestItem> _manifest;
public IReadOnlyDictionary<string, RobustManifestItem> Manifest => _manifest;
public HashApi(List<RobustManifestItem> manifest, IFileApi fileApi)
public HashApi(List<RobustManifestItem> manifest, IReadWriteFileApi fileApi)
{
_fileApi = fileApi;
Manifest = new Dictionary<string, RobustManifestItem>();
foreach (var item in manifest) Manifest.TryAdd(item.Path, item);
_manifest = new Dictionary<string, RobustManifestItem>();
foreach (var item in manifest) _manifest.TryAdd(item.Path, item);
}
public bool TryOpen(string path,[NotNullWhen(true)] out Stream? stream)
{
if (path[0] == '/') path = path.Substring(1);
if (Manifest.TryGetValue(path, out var a) && _fileApi.TryOpen(a.Hash, out stream))
if (_manifest.TryGetValue(path, out var a) && _fileApi.TryOpen(GetManifestPath(a), out stream))
return true;
stream = null;
return false;
}
public IEnumerable<string> AllFiles => Manifest.Keys;
public bool TryOpen(RobustManifestItem item ,[NotNullWhen(true)] out Stream? stream){
if(_fileApi.TryOpen(GetManifestPath(item), out stream))
return true;
stream = null;
return false;
}
public bool TryOpenByHash(string hash ,[NotNullWhen(true)] out Stream? stream){
if(_fileApi.TryOpen(GetManifestPath(hash), out stream))
return true;
stream = null;
return false;
}
public bool Save(RobustManifestItem item, Stream stream){
return _fileApi.Save(GetManifestPath(item), stream);
}
public bool Has(RobustManifestItem item){
return _fileApi.Has(GetManifestPath(item));
}
private string GetManifestPath(RobustManifestItem item){
return GetManifestPath(item.Hash);
}
public static string GetManifestPath(string hash){
return hash[0].ToString() + hash[1].ToString() + '/' + hash;
}
public IEnumerable<string> AllFiles => _manifest.Keys;
}

View File

@@ -4,7 +4,7 @@ public class LoginInfo
{
public Guid UserId { get; set; }
public string Username { get; set; } = default!;
public LoginToken Token { get; set; }
public LoginToken Token { get; set; } = default!;
public override string ToString()
{

View File

@@ -2,7 +2,7 @@ namespace Nebula.Shared.Models;
public class RobustBuildInfo
{
public ServerInfo BuildInfo;
public ServerInfo BuildInfo = default!;
public RobustManifestInfo RobustManifestInfo;
public RobustUrl Url;
public RobustUrl Url = default!;
}

View File

@@ -2,6 +2,7 @@
using System.Globalization;
using System.Net.Http.Headers;
using System.Numerics;
using Nebula.Shared.FileApis;
using Nebula.Shared.FileApis.Interfaces;
using Nebula.Shared.Models;
using Nebula.Shared.Utils;
@@ -15,7 +16,7 @@ public partial class ContentService
return fileService.ContentFileApi.Has(item.Hash);
}
public async Task<List<RobustManifestItem>> EnsureItems(ManifestReader manifestReader, Uri downloadUri,
public async Task<HashApi> EnsureItems(ManifestReader manifestReader, Uri downloadUri,
ILoadingHandler loadingHandler,
CancellationToken cancellationToken)
{
@@ -25,26 +26,22 @@ public partial class ContentService
while (manifestReader.TryReadItem(out var item))
{
if (cancellationToken.IsCancellationRequested)
{
debugService.Log("ensuring is cancelled!");
return [];
}
if (!CheckManifestExist(item.Value))
items.Add(item.Value);
throw new TaskCanceledException();
allItems.Add(item.Value);
}
var hashApi = new HashApi(allItems, fileService.ContentFileApi);
items = allItems.Where(a=> !hashApi.Has(a)).ToList();
debugService.Log("Download Count:" + items.Count);
await Download(downloadUri, items, hashApi, loadingHandler, cancellationToken);
await Download(downloadUri, items, loadingHandler, cancellationToken);
fileService.ManifestItems = allItems;
return allItems;
return hashApi;
}
public async Task<List<RobustManifestItem>> EnsureItems(RobustManifestInfo info, ILoadingHandler loadingHandler,
public async Task<HashApi> EnsureItems(RobustManifestInfo info, ILoadingHandler loadingHandler,
CancellationToken cancellationToken)
{
debugService.Log("Getting manifest: " + info.Hash);
@@ -71,11 +68,12 @@ public partial class ContentService
CancellationToken cancellationToken)
{
debugService.Log("Unpack manifest files");
var items = await EnsureItems(info, loadingHandler, cancellationToken);
var hashApi = await EnsureItems(info, loadingHandler, cancellationToken);
var items = hashApi.Manifest.Values.ToList();
loadingHandler.AppendJob(items.Count);
foreach (var item in items)
{
if (fileService.ContentFileApi.TryOpen(item.Hash, out var stream))
if (hashApi.TryOpen(item, out var stream))
{
debugService.Log($"Unpack {item.Hash} to: {item.Path}");
otherApi.Save(item.Path, stream);
@@ -90,7 +88,7 @@ public partial class ContentService
}
}
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, ILoadingHandler loadingHandler,
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, HashApi hashApi, ILoadingHandler loadingHandler,
CancellationToken cancellationToken)
{
if (toDownload.Count == 0 || cancellationToken.IsCancellationRequested)
@@ -189,10 +187,6 @@ public partial class ContentService
EnsureBuffer(ref readBuffer, length);
var data = readBuffer.AsMemory(0, length);
// Data to write to database.
var compression = ContentCompressionScheme.None;
var writeData = data;
if (preCompressed)
{
// Compressed length from extended header.
@@ -210,10 +204,6 @@ public partial class ContentService
if (decompressedLength != data.Length)
throw new Exception($"Compressed blob {i} had incorrect decompressed size!");
// Set variables so that the database write down below uses them.
compression = ContentCompressionScheme.ZStd;
writeData = compressedData;
}
else
{
@@ -225,25 +215,8 @@ public partial class ContentService
await stream.ReadExactAsync(data, null);
}
if (!preCompressed)
{
// File wasn't pre-compressed. We should try to manually compress it to save space in DB.
EnsureBuffer(ref compressBuffer, ZStd.CompressBound(data.Length));
var compressLength = compressContext!.Compress(compressBuffer, data.Span);
// Don't bother saving compressed data if it didn't save enough space.
if (compressLength + 10 < length)
{
// Set variables so that the database write down below uses them.
compression = ContentCompressionScheme.ZStd;
writeData = compressBuffer.AsMemory(0, compressLength);
}
}
using var fileStream = new MemoryStream(data.ToArray());
fileService.ContentFileApi.Save(item.Hash, fileStream);
hashApi.Save(item, fileStream);
debugService.Log("file saved:" + item.Path);
loadingHandler.AppendResolvedJob();

View File

@@ -14,14 +14,11 @@ public class FileService
Environment.SpecialFolder.ApplicationData), "Datum");
private readonly DebugService _debugService;
public readonly IReadWriteFileApi ConfigurationApi;
public readonly IReadWriteFileApi ConfigurationApi;
public readonly IReadWriteFileApi ContentFileApi;
public readonly IReadWriteFileApi EngineFileApi;
public readonly IReadWriteFileApi ManifestFileApi;
private HashApi? _hashApi;
public FileService(DebugService debugService)
{
_debugService = debugService;
@@ -29,21 +26,15 @@ public class FileService
EngineFileApi = CreateFileApi("engine");
ManifestFileApi = CreateFileApi("manifest");
ConfigurationApi = CreateFileApi("config");
}
public List<RobustManifestItem> ManifestItems
{
set => _hashApi = new HashApi(value, ContentFileApi);
}
public HashApi HashApi
{
get
{
if (_hashApi is null) throw new Exception("Hash API is not initialized!");
return _hashApi;
// Some migrating think
foreach(var file in ContentFileApi.AllFiles){
if(file.Contains("\\") || !ContentFileApi.TryOpen(file, out var stream)) continue;
ContentFileApi.Save(HashApi.GetManifestPath(file), stream);
stream.Dispose();
ContentFileApi.Remove(file);
}
set => _hashApi = value;
}
public IReadWriteFileApi CreateFileApi(string path)

View File

@@ -8,7 +8,6 @@ public sealed class RunnerService(
ContentService contentService,
DebugService debugService,
ConfigurationService varService,
FileService fileService,
EngineService engineService,
AssemblyService assemblyService)
{
@@ -20,7 +19,7 @@ public sealed class RunnerService(
var engine = await engineService.EnsureEngine(buildInfo.BuildInfo.Build.EngineVersion);
if (engine is null)
throw new Exception("Engine version is not usable: " + buildInfo.BuildInfo.Build.EngineVersion);
throw new Exception("Engine version not found: " + buildInfo.BuildInfo.Build.EngineVersion);
await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
await engineService.EnsureEngineModules("Robust.Client.WebView", buildInfo.BuildInfo.Build.EngineVersion);
@@ -35,13 +34,13 @@ public sealed class RunnerService(
var engine = await engineService.EnsureEngine(buildInfo.BuildInfo.Build.EngineVersion);
if (engine is null)
throw new Exception("Engine version is not usable: " + buildInfo.BuildInfo.Build.EngineVersion);
throw new Exception("Engine version not found: " + buildInfo.BuildInfo.Build.EngineVersion);
await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
var hashApi = await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
var extraMounts = new List<ApiMount>
{
new(fileService.HashApi, "/")
new(hashApi, "/")
};
var module =