yavsc/src/Yavsc.Server/Services/DiskUsageTracker.cs
2025-02-15 12:45:27 +00:00

101 lines
3 KiB
C#

using Microsoft.Extensions.Options;
using Yavsc;
using Yavsc.Models;
using Yavsc.Services;
public class DiskUsageTracker : IDiskUsageTracker
{
public class DUTInfo
{
public DUTInfo()
{
Creation = DateTime.Now;
}
public long Usage { get; set; }
public long Quota { get; set; }
public readonly DateTime Creation;
}
readonly Dictionary<string, DUTInfo> DiskUsage;
readonly ApplicationDbContext context;
readonly int ulistLength;
public DiskUsageTracker(IOptions<SiteSettings> options, ApplicationDbContext context)
{
ulistLength = options.Value.DUUserListLen;
DiskUsage = new Dictionary<string, DUTInfo>();
this.context = context;
}
readonly static object userInfoLock = new object();
DUTInfo GetInfo(string username)
{
lock (userInfoLock)
{
if (!DiskUsage.ContainsKey(username))
{
var user = context.Users.SingleOrDefault(u => u.UserName == username);
if (user == null) throw new Exception($"Not an user : {username}");
DUTInfo usage = new DUTInfo
{
Usage = user.DiskUsage,
Quota = user.DiskQuota
};
DiskUsage.Add(username, usage);
if (DiskUsage.Count > ulistLength)
{
// remove the oldest
var oldestts = DateTime.Now;
DUTInfo oinfo = null;
string ouname = null;
foreach (var diskusage in DiskUsage)
{
if (oldestts > usage.Creation)
{
oldestts = diskusage.Value.Creation;
ouname = diskusage.Key;
oinfo = diskusage.Value;
}
}
var ouser = context.Users.SingleOrDefault(u => u.UserName == ouname);
ouser.DiskUsage = oinfo.Usage;
context.SaveChanges();
DiskUsage.Remove(ouname);
}
return usage;
}
return DiskUsage[username];
}
}
public bool GetSpace(string userName, long space)
{
var info = GetInfo(userName);
if (info.Quota < info.Usage + space) return false;
info.Usage += space;
#pragma warning disable CS4014
SaveUserUsage(userName,info.Usage);
#pragma warning restore CS4014
return true;
}
public void Release(string userName, long space)
{
var info = GetInfo(userName);
info.Usage -= space;
#pragma warning disable CS4014
SaveUserUsage(userName,info.Usage);
#pragma warning restore CS4014
}
async Task SaveUserUsage(string username, long usage)
{
await Task.Run(() =>
{
var ouser = context.Users.SingleOrDefault(u => u.UserName == username);
ouser.DiskUsage = usage;
context.SaveChanges();
});
}
}