Skip to content

Commit

Permalink
feat: 文件缓存
Browse files Browse the repository at this point in the history
  • Loading branch information
SALTWOOD committed Mar 30, 2024
1 parent 0eb9f73 commit 8856f6d
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 5 deletions.
4 changes: 2 additions & 2 deletions CSharp-OpenBMCLAPI/Modules/Cluster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class Cluster : RunnableBase
public bool IsEnabled { get; set; }
public bool WantEnable { get; set; }
private Task? _keepAlive;
protected IStorage storage;
internal IStorage storage;
protected AccessCounter counter;
public CancellationTokenSource cancellationSrc = new CancellationTokenSource();
public WebApplication? application = null;
Expand All @@ -58,7 +58,7 @@ public Cluster(ClusterInfo info, TokenManager token) : base()
client = HttpRequest.client;
client.DefaultRequestHeaders.Authorization = new("Bearer", SharedData.Token?.Token.token);

this.storage = new FileStorage(SharedData.Config.clusterFileDirectory);
this.storage = new CachedStorage(new FileStorage(SharedData.Config.clusterFileDirectory));

this.counter = new();
InitializeSocket();
Expand Down
5 changes: 2 additions & 3 deletions CSharp-OpenBMCLAPI/Modules/HttpServiceProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,15 @@ public static async Task Api(HttpContext context, string query, Cluster cluster)
await context.Response.WriteAsync(JsonConvert.SerializeObject(SharedData.DataStatistician.Dashboard));
break;
case "system":

await context.Response.WriteAsync(JsonConvert.SerializeObject(new
{
memory = SharedData.DataStatistician.Memory,
connections = SharedData.DataStatistician.Connections,
cpu = SharedData.DataStatistician.Cpu,
cache = new
{
total = 0,
bytes = 0
total = (cluster.storage as ICachedStorage != null) ? ((ICachedStorage)cluster.storage).GetCachedFiles() : 0,
bytes = (cluster.storage as ICachedStorage != null) ? ((ICachedStorage)cluster.storage).GetCachedMemory() : 0
}
}));
break;
Expand Down
189 changes: 189 additions & 0 deletions CSharp-OpenBMCLAPI/Modules/Storage/CachedStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TeraIO.Runnable;

namespace CSharpOpenBMCLAPI.Modules.Storage
{
public struct CachedFile
{
private object locker;
internal byte[] content;
public long LastAccessTime { get; private set; }
public byte[] Content
{
get
{
lock (locker)
{
LastAccessTime = DateTimeOffset.Now.ToUnixTimeSeconds();
return content;
}
}
}

public CachedFile(byte[] content)
{
this.content = content;
locker = new object();
}
}

public class CachedStorage : ICachedStorage
{
private Dictionary<string, CachedFile> cache = new();
private IStorage storage;
private Task? _cleanupTask;
public int cleanupTime = 3 * 60;

public CachedStorage(IStorage storage)
{
this.storage = storage;
}

public bool Exists(string hashPath)
{
return cache.ContainsKey(hashPath) || storage.Exists(hashPath);
}

public async Task<FileAccessInfo> Express(string hashPath, HttpContext context)
{
if (!cache.ContainsKey(hashPath))
{
byte[] bytes = this.ReadFile(hashPath);
this[hashPath] = new CachedFile(bytes);
return new FileAccessInfo
{
hits = 1,
bytes = bytes.LongLength
};
}
else
{
await context.Response.BodyWriter.WriteAsync(this[hashPath].Content);
return new FileAccessInfo
{
hits = 1,
bytes = GetFileSize(hashPath)
};
}
}

public void GarbageCollect(IEnumerable<ApiFileInfo> files)
{
lock (cache)
{
GarbageCollectInternal();
}
storage.GarbageCollect(files);
}

private void GarbageCollectInternal()
{
List<string> deleted = new();
foreach (var file in cache)
{
if (file.Value.LastAccessTime + cleanupTime < DateTimeOffset.Now.ToUnixTimeSeconds())
{
deleted.Add(file.Key);
}
}
foreach (var file in deleted)
{
cache.Remove(file);
}
}

public string GetAbsolutePath(string path)
{
return storage.GetAbsolutePath(path);
}

public long GetFileSize(string hashPath)
{
if (cache.ContainsKey(hashPath)) return cache[hashPath].content.LongLength;
return storage.GetFileSize(hashPath);
}

public IEnumerable<ApiFileInfo> GetMissingFiles(IEnumerable<ApiFileInfo> files)
{
return storage.GetMissingFiles(files);
}

public void Initialize()
{
_cleanupTask = Task.Run(() =>
{
while (true)
{
GarbageCollectInternal();
Thread.Sleep(60 * 1000);
}
});
storage.Initialize();
}

public byte[] ReadFile(string hashPath)
{
if (cache.ContainsKey(hashPath))
{
lock (cache)
{
return this[hashPath].Content;
}
}
else
{
byte[] bytes = storage.ReadFile(hashPath);
cache.Add(hashPath, new CachedFile(bytes));
return bytes;
}
}

public Stream ReadFileStream(string hashPath)
{
if (cache.ContainsKey(hashPath))
{
lock (cache)
{
return new MemoryStream(this[hashPath].Content);
}
}
return storage.ReadFileStream(hashPath);
}

public void WriteFile(string hashPath, byte[] buffer)
{
if (cache.ContainsKey(hashPath))
{
lock (cache)
{
CachedFile temp = this[hashPath];
temp.content = buffer;
this[hashPath] = temp;
}
return;
}
storage.WriteFile(hashPath, buffer);
}

public long GetCachedMemory()
{
return cache.Sum(c => c.Value.content.LongLength);
}

public long GetCachedFiles()
{
return cache.Count;
}

public CachedFile this[string key]
{
get => cache[key];
set => cache[key] = value;
}
}
}
14 changes: 14 additions & 0 deletions CSharp-OpenBMCLAPI/Modules/Storage/ICachedStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpOpenBMCLAPI.Modules.Storage
{
public interface ICachedStorage : IStorage
{
public abstract long GetCachedFiles();
public abstract long GetCachedMemory();
}
}

0 comments on commit 8856f6d

Please sign in to comment.