Use seekable streams for plate1 storage (#146)

This commit is contained in:
Taylor Southwick 2020-10-19 16:58:06 -07:00 коммит произвёл GitHub
Родитель beb324f457
Коммит c397c225cd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 76 добавлений и 30 удалений

Просмотреть файл

@ -29,7 +29,7 @@ namespace WWT.Azure
services.AddTransient(_ => new BlobServiceClient(azureOptions.StorageAccount));
}
services.AddSingleton<IPlateTilePyramid, AzurePlateTilePyramid>();
services.AddSingleton<IPlateTilePyramid, SeekableAzurePlateTilePyramid>();
}
else
{

Просмотреть файл

@ -0,0 +1,56 @@
using Azure.Storage.Blobs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using WWTWebservices;
namespace WWT.Azure
{
public class SeekableAzurePlateTilePyramid : IPlateTilePyramid
{
private readonly Func<string, BlobClient> _blobRetriever;
private readonly BlobContainerClient _container;
public SeekableAzurePlateTilePyramid(AzurePlateTilePyramidOptions options, BlobServiceClient service)
{
_container = service.GetBlobContainerClient(options.Container);
var cache = new ConcurrentDictionary<string, BlobClient>();
_blobRetriever = plateName => cache.GetOrAdd(plateName, _container.GetBlobClient);
}
Stream IPlateTilePyramid.GetStream(string pathPrefix, string plateName, int level, int x, int y)
=> GetStream(plateName, level, x, y);
public Stream GetStream(string plateName, int level, int x, int y)
{
var client = _blobRetriever(plateName);
var download = client.OpenRead();
return PlateTilePyramid.GetImageStream(download, level, x, y);
}
public async IAsyncEnumerable<string> GetPlateNames([EnumeratorCancellation] CancellationToken token)
{
await foreach (var item in _container.GetBlobsByHierarchyAsync(delimiter: "/", cancellationToken: token))
{
var prefix = item.Prefix.TrimEnd('/');
yield return $"{prefix}.plate";
}
}
Stream IPlateTilePyramid.GetStream(string pathPrefix, string plateName, int tag, int level, int x, int y)
=> GetStream(plateName, tag, level, x, y);
public Stream GetStream(string plateName, int tag, int level, int x, int y)
{
var client = _blobRetriever(plateName);
var stream = client.OpenRead();
return PlateFile2.GetImageStream(stream, tag, level, x, y);
}
}
}

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.IO;
using WWT.PlateFiles;
/* Jonathan Fay wrote this, except for the bits polluted by Dinoj, which are between <dinoj>...</dinoj> tags
* The header information in the .plate files is being upgraded.
@ -103,7 +104,7 @@ namespace WWTWebservices
fs.Close();
}
}
public void AddStream(Stream inputStream, int level, int x, int y)
{
@ -123,8 +124,7 @@ namespace WWTWebservices
int lenRead = inputStream.Read(buf, 0, len);
fileStream.Write(buf, 0, len);
inputStream.Close();
}
}
public void UpdateHeaderAndClose()
{
@ -235,6 +235,17 @@ namespace WWTWebservices
}
return null;
}
public static Stream GetImageStream(Stream f, int level, int x, int y)
{
var offset = GetFileIndexOffset(level, x, y);
f.Seek(offset, SeekOrigin.Begin);
var start = GetNodeInfo(f, offset, out var length);
return new StreamSlice(f, start, length);
}
static public Stream GetFileStream(string filename, int level, int x, int y)
{
uint offset = GetFileIndexOffset(level, x, y);
@ -254,28 +265,8 @@ namespace WWTWebservices
}
return ms;
}
/*
public byte[] GetTile(int level, int x, int y)
{
uint offset = GetFileIndexOffset(level, x, y);
uint length;
uint start;
MemoryStream ms = null;
if (_readStream == null)
_readStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_readStream.Seek(offset, SeekOrigin.Begin);
start = GetNodeInfo(_readStream, offset, out length);
if (length == 0)
return null;
byte[] buffer = new byte[length];
_readStream.Seek(start, SeekOrigin.Begin);
_readStream.Read(buffer, 0, (int)length);
return buffer;
}
*/
static public uint GetNodeInfo(FileStream fs, uint offset, out uint length)
public static uint GetNodeInfo(Stream fs, uint offset, out uint length)
{
Byte[] buf = new Byte[8];
fs.Seek(offset, SeekOrigin.Begin);
@ -332,7 +323,6 @@ namespace WWTWebservices
{
this.level = level;
fileMap = new NodeInfo[(int)Math.Pow(2, level), (int)Math.Pow(2, level)];
}
}

Просмотреть файл

@ -31,7 +31,7 @@ namespace WWT.Providers
{
context.Response.ContentType = "image/png";
using (var s = _plateTile.GetStream(_options.WwtTilesDir, "dssterrapixel.plate", level, tileX, tileY))
using (var s = _plateTile.GetStream(_options.WwtTilesDir, "DSSTerraPixel.plate", level, tileX, tileY))
{
s.CopyTo(context.Response.OutputStream);
context.Response.Flush();

Просмотреть файл

@ -33,7 +33,7 @@ namespace WWT.Providers
{
context.Response.ContentType = "image/png";
using (var s = _plateTile.GetStream(_options.WwtTilesDir, "dsstoast.plate", level, tileX, tileY))
using (var s = _plateTile.GetStream(_options.WwtTilesDir, "DSSToast.plate", level, tileX, tileY))
{
s.CopyTo(context.Response.OutputStream);
context.Response.Flush();

Просмотреть файл

@ -21,7 +21,7 @@ namespace WWT.Providers.Tests
}
else if (level < 8)
{
return plateTiles.GetStream(Options.WwtTilesDir, "dssterrapixel.plate", level, x, y);
return plateTiles.GetStream(Options.WwtTilesDir, "DSSTerraPixel.plate", level, x, y);
}
else
{

Просмотреть файл

@ -21,7 +21,7 @@ namespace WWT.Providers.Tests
}
else if (level < 8)
{
return plateTiles.GetStream(Options.WwtTilesDir, "dsstoast.plate", level, x, y);
return plateTiles.GetStream(Options.WwtTilesDir, "DSSToast.plate", level, x, y);
}
else
{