1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 03:27:24 +08:00
osu-lazer/osu.Game/IO/FileStore.cs

115 lines
3.6 KiB
C#
Raw Normal View History

2018-01-05 19:21:19 +08:00
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.IO;
using System.Linq;
using osu.Framework.Extensions;
using osu.Framework.IO.Stores;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Database;
namespace osu.Game.IO
{
/// <summary>
/// Handles the Store and retrieval of Files/FileSets to the database backing
/// </summary>
public class FileStore : DatabaseBackedStore
{
public readonly IResourceStore<byte[]> Store;
public new Storage Storage => base.Storage;
public FileStore(IDatabaseContextFactory contextFactory, Storage storage) : base(contextFactory, storage.GetStorageForDirectory(@"files"))
{
Store = new StorageBackedResourceStore(Storage);
}
public FileInfo Add(Stream data, bool reference = true)
{
2018-02-12 16:55:11 +08:00
using (var usage = ContextFactory.GetForWrite())
{
string hash = data.ComputeSHA2Hash();
var existing = usage.Context.FileInfo.FirstOrDefault(f => f.Hash == hash);
2018-02-12 16:55:11 +08:00
var info = existing ?? new FileInfo { Hash = hash };
2018-02-12 16:55:11 +08:00
string path = info.StoragePath;
2018-02-12 16:55:11 +08:00
// we may be re-adding a file to fix missing store entries.
if (!Storage.Exists(path))
{
data.Seek(0, SeekOrigin.Begin);
2018-02-12 16:55:11 +08:00
using (var output = Storage.GetStream(path, FileAccess.Write))
data.CopyTo(output);
2018-02-12 16:55:11 +08:00
data.Seek(0, SeekOrigin.Begin);
}
2018-02-12 16:55:11 +08:00
if (reference || existing == null)
Reference(info);
2018-02-12 16:55:11 +08:00
return info;
}
}
2018-02-12 16:55:11 +08:00
public void Reference(params FileInfo[] files)
{
if (files.Length == 0) return;
2018-02-12 16:55:11 +08:00
using (var usage = ContextFactory.GetForWrite())
{
2018-02-12 16:55:11 +08:00
var context = usage.Context;
2017-10-16 12:09:10 +08:00
2018-02-12 16:55:11 +08:00
foreach (var f in files.GroupBy(f => f.ID))
{
var refetch = context.Find<FileInfo>(f.First().ID) ?? f.First();
refetch.ReferenceCount += f.Count();
context.FileInfo.Update(refetch);
}
}
}
2018-02-12 16:55:11 +08:00
public void Dereference(params FileInfo[] files)
{
if (files.Length == 0) return;
2018-02-12 16:55:11 +08:00
using (var usage = ContextFactory.GetForWrite())
{
2018-02-12 16:55:11 +08:00
var context = usage.Context;
2018-02-12 16:55:11 +08:00
foreach (var f in files.GroupBy(f => f.ID))
{
var refetch = context.FileInfo.Find(f.Key);
refetch.ReferenceCount -= f.Count();
context.FileInfo.Update(refetch);
}
2017-10-16 12:09:10 +08:00
}
}
public override void Cleanup()
{
2018-02-12 16:55:11 +08:00
using (var usage = ContextFactory.GetForWrite())
{
2018-02-12 16:55:11 +08:00
var context = usage.Context;
foreach (var f in context.FileInfo.Where(f => f.ReferenceCount < 1))
2017-10-05 03:52:12 +08:00
{
2018-02-12 16:55:11 +08:00
try
{
Storage.Delete(f.StoragePath);
context.FileInfo.Remove(f);
}
catch (Exception e)
{
Logger.Error(e, $@"Could not delete beatmap {f}");
}
2017-10-05 03:52:12 +08:00
}
}
}
}
2017-10-05 03:52:12 +08:00
}