Use seekable streams for plate1 storage (#146)
This commit is contained in:
Родитель
beb324f457
Коммит
c397c225cd
|
@ -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
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче