2020-03-05 00:02:16 +00:00
|
|
|
|
using System;
|
2020-04-03 03:57:59 +00:00
|
|
|
|
using System.Collections.Generic;
|
2020-03-05 00:02:16 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.MemoryMappedFiles;
|
2020-05-28 02:43:57 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2020-03-05 00:02:16 +00:00
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Common
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Memory allocator that stores data via memory mapping to a on-disk file. Disposing of this object
|
|
|
|
|
/// deletes the memory mapped file
|
|
|
|
|
/// </summary>
|
2020-05-28 02:43:57 +00:00
|
|
|
|
public class DiskSlabAllocator : IAsyncDisposable
|
2020-03-05 00:02:16 +00:00
|
|
|
|
{
|
2020-03-28 13:33:39 +00:00
|
|
|
|
private readonly TempFile _file;
|
|
|
|
|
private readonly MemoryMappedFile _mmap;
|
2020-03-05 00:02:16 +00:00
|
|
|
|
private long _head = 0;
|
2020-03-28 13:33:39 +00:00
|
|
|
|
private readonly FileStream _fileStream;
|
2020-05-28 02:43:57 +00:00
|
|
|
|
private List<IAsyncDisposable> _allocated = new List<IAsyncDisposable>();
|
2020-04-03 03:57:59 +00:00
|
|
|
|
private long _size;
|
2020-03-05 00:02:16 +00:00
|
|
|
|
|
2020-03-09 20:38:35 +00:00
|
|
|
|
public DiskSlabAllocator(long size)
|
2020-03-05 00:02:16 +00:00
|
|
|
|
{
|
2020-03-09 20:38:35 +00:00
|
|
|
|
_file = new TempFile();
|
|
|
|
|
_fileStream = _file.File.Open(FileMode.Create, FileAccess.ReadWrite);
|
2020-07-19 23:09:59 +00:00
|
|
|
|
_size = Math.Max(size, 1024);
|
2020-03-09 20:38:35 +00:00
|
|
|
|
_mmap = MemoryMappedFile.CreateFromFile(_fileStream, null, size, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false);
|
2020-03-05 00:02:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Stream Allocate(long size)
|
|
|
|
|
{
|
|
|
|
|
lock (this)
|
|
|
|
|
{
|
2020-04-15 11:53:49 +00:00
|
|
|
|
// This can happen at times due to differences in compression sizes
|
2020-04-03 03:57:59 +00:00
|
|
|
|
if (_head + size >= _size)
|
2020-04-15 11:53:49 +00:00
|
|
|
|
{
|
|
|
|
|
return new MemoryStream();
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-05 00:02:16 +00:00
|
|
|
|
var startAt = _head;
|
|
|
|
|
_head += size;
|
2020-04-03 03:57:59 +00:00
|
|
|
|
var stream = _mmap.CreateViewStream(startAt, size, MemoryMappedFileAccess.ReadWrite);
|
|
|
|
|
_allocated.Add(stream);
|
|
|
|
|
return stream;
|
2020-03-05 00:02:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-28 02:43:57 +00:00
|
|
|
|
public async ValueTask DisposeAsync()
|
2020-03-05 00:02:16 +00:00
|
|
|
|
{
|
2020-05-28 02:43:57 +00:00
|
|
|
|
foreach (var allocated in _allocated)
|
|
|
|
|
await allocated.DisposeAsync();
|
2020-04-03 23:23:13 +00:00
|
|
|
|
_mmap.Dispose();
|
2020-05-28 02:43:57 +00:00
|
|
|
|
await _fileStream.DisposeAsync();
|
|
|
|
|
await _file.DisposeAsync();
|
2020-03-05 00:02:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|