Skip to content

Commit

Permalink
Merge pull request #87 from twsouthwick/DSS-provider
Browse files Browse the repository at this point in the history
Abstract file access pattern for DSS provider
  • Loading branch information
pkgw authored Sep 22, 2020
2 parents 25a7d26 + ce62eb3 commit 54c4778
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 48 deletions.
18 changes: 17 additions & 1 deletion WWTMVC5/App_Start/UnityConfig.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using Azure.Identity;
using Microsoft.Practices.Unity;
using System;
using System.Configuration;
using System.Linq;
using Microsoft.Practices.Unity;
using WWT.Providers;
using WWTWebservices;
using WWTWebservices.Azure;

namespace WWTMVC5
{
Expand Down Expand Up @@ -35,6 +38,7 @@ public static IUnityContainer GetConfiguredContainer()
public static void RegisterTypes(IUnityContainer container)
{
RegisterRequestProviders(container);
RegisterPlateFileProvider(container);

// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
Expand All @@ -54,5 +58,17 @@ private static void RegisterRequestProviders(IUnityContainer container)
container.RegisterType(type);
}
}

private static void RegisterPlateFileProvider(IUnityContainer container)
{
if (ConfigReader<bool>.GetSetting("UseAzurePlateFiles"))
{
container.RegisterInstance<IPlateTilePyramid>(new AzurePlateTilePyramid(ConfigurationManager.AppSettings["AzurePlateFileContainer"], new DefaultAzureCredential()));
}
else
{
container.RegisterType<IPlateTilePyramid, ConfigurationManagerFilePlateTilePyramid>(new ContainerControlledLifetimeManager());
}
}
}
}
10 changes: 4 additions & 6 deletions WWTMVC5/WWTMVC5.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,10 @@
<Project>{ee4a3106-572b-4ef4-9ab5-a22643309a57}</Project>
<Name>WWT.Providers</Name>
</ProjectReference>
<ProjectReference Include="..\WWTWebservices.Azure\WWTWebservices.Azure.csproj">
<Project>{FB9956F9-B0FF-4E45-BAA5-4180DA8A12A9}</Project>
<Name>WWTWebservices.Azure</Name>
</ProjectReference>
<ProjectReference Include="..\WWTWebservices\WWTWebservices.csproj">
<Project>{1cf4d986-51ad-43f8-a84a-38b6ecba2172}</Project>
<Name>WWTWebservices</Name>
Expand Down Expand Up @@ -1443,9 +1447,6 @@
<PackageReference Include="Microsoft.IdentityModel">
<Version>6.1.7600.16394</Version>
</PackageReference>
<PackageReference Include="Microsoft.WindowsAzure.ConfigurationManager">
<Version>3.2.3</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>10.0.3</Version>
</PackageReference>
Expand All @@ -1461,9 +1462,6 @@
<PackageReference Include="WebGrease">
<Version>1.6.0</Version>
</PackageReference>
<PackageReference Include="WindowsAzure.Storage">
<Version>4.3.0</Version>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
Expand Down
4 changes: 4 additions & 0 deletions WWTMVC5/Web.config
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ Content-Type: application/x-wt-->
<add key="ResourcesVersion" value="5.3.65"/>
<add key="HomePageCacheTimeout" value="5"/>

<!-- Azure storage access for plate files-->
<add key="UseAzurePlateFiles" value="false"/>
<add key="AzurePlateFileContainer" value="https://127.0.0.1:10000/devstoreaccount1"/>

<!-- Overridden with Configuration Builders -->
<add key="TourCache" value=""/>
<add key="WWTTilesDir" value=""/>
Expand Down
6 changes: 6 additions & 0 deletions WWTWebSiteOnly.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WWTWebservices.Azure", "WWTWebservices.Azure\WWTWebservices.Azure.csproj", "{FB9956F9-B0FF-4E45-BAA5-4180DA8A12A9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -46,6 +48,10 @@ Global
{31DC6DC8-AF43-41AC-B9B7-7E77E6CD8950}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31DC6DC8-AF43-41AC-B9B7-7E77E6CD8950}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31DC6DC8-AF43-41AC-B9B7-7E77E6CD8950}.Release|Any CPU.Build.0 = Release|Any CPU
{FB9956F9-B0FF-4E45-BAA5-4180DA8A12A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FB9956F9-B0FF-4E45-BAA5-4180DA8A12A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FB9956F9-B0FF-4E45-BAA5-4180DA8A12A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB9956F9-B0FF-4E45-BAA5-4180DA8A12A9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
64 changes: 64 additions & 0 deletions WWTWebservices.Azure/AzurePlateTilePyramid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Azure.Core;
using Azure.Storage.Blobs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;

namespace WWTWebservices.Azure
{
public class AzurePlateTilePyramid : IPlateTilePyramid
{
private readonly Dictionary<string, (string container, string blob)> _plateNameMapping = new Dictionary<string, (string, string)>(StringComparer.OrdinalIgnoreCase)
{
{ "dssterrapixel.plate", ("dss", "DSSTerraPixelL{0}X{1}Y{2}.png") }
};

private readonly BlobServiceClient _service;
private readonly ConcurrentDictionary<string, BlobContainerClient> _containers;

public AzurePlateTilePyramid(string storageUri, TokenCredential credentials)
{
_service = new BlobServiceClient(new Uri(storageUri), credentials);
_containers = new ConcurrentDictionary<string, BlobContainerClient>();
}

public Stream GetStream(string pathPrefix, string plateName, int level, int x, int y)
{
var container = _containers.GetOrAdd(plateName, p =>
{
var name = GetBlobContainerName(plateName);
return _service.GetBlobContainerClient(name);
});

var blobName = GetBlobName(plateName, level, x, y);
var client = container.GetBlobClient(blobName);
var download = client.Download();

return download.Value.Content;
}

private string GetBlobContainerName(string plateName)
{
if (_plateNameMapping.TryGetValue(plateName, out var info))
{
return info.container;
}

return Path.GetFileNameWithoutExtension(plateName).ToLowerInvariant();
}

private string GetBlobName(string plateName, int level, int x, int y)
{
var blobFormat = "L{0}X{1}Y{2}.png";

if (_plateNameMapping.TryGetValue(plateName, out var info))
{
blobFormat = info.blob;
}

return string.Format(blobFormat, level, x, y);
}
}
}
19 changes: 19 additions & 0 deletions WWTWebservices.Azure/WWTWebservices.Azure.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.6.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\WWTWebservices\WWTWebservices.csproj" />
</ItemGroup>

<ItemGroup>
<Reference Include="System.Configuration" />
</ItemGroup>

</Project>
17 changes: 17 additions & 0 deletions WWTWebservices/ConfigurationManagerFilePlateTilePyramid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.IO;

namespace WWTWebservices
{
public class ConfigurationManagerFilePlateTilePyramid : IPlateTilePyramid
{
public Stream GetStream(string pathPrefix, string plateName, int level, int x, int y)
{
if (string.IsNullOrEmpty(pathPrefix))
{
throw new System.ArgumentException($"'{nameof(pathPrefix)}' cannot be null or empty", nameof(pathPrefix));
}

return PlateTilePyramid.GetFileStream(Path.Combine(pathPrefix, plateName), level, x, y);
}
}
}
9 changes: 9 additions & 0 deletions WWTWebservices/IPlateTilePyramid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.IO;

namespace WWTWebservices
{
public interface IPlateTilePyramid
{
Stream GetStream(string pathPrefix, string plateName, int level, int x, int y);
}
}
3 changes: 1 addition & 2 deletions WWTWebservices/PlateTilePyramid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,14 +238,13 @@ public Stream GetFileStream(int level, int x, int y)
static public Stream GetFileStream(string filename, int level, int x, int y)
{
uint offset = GetFileIndexOffset(level, x, y);
uint length;
uint start;

MemoryStream ms = null;
using (FileStream f = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
f.Seek(offset, SeekOrigin.Begin);
start = GetNodeInfo(f, offset, out length);
start = GetNodeInfo(f, offset, out var length);

byte[] buffer = new byte[length];
f.Seek(start, SeekOrigin.Begin);
Expand Down
2 changes: 1 addition & 1 deletion WWTWebservices/WWTWebservices.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>net45</TargetFramework>
<TargetFramework>net48</TargetFramework>
<OutputType>Library</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWindowsForms>true</UseWindowsForms>
Expand Down
71 changes: 33 additions & 38 deletions src/WWT.Providers/Providers/DSSProvider.cs
Original file line number Diff line number Diff line change
@@ -1,70 +1,65 @@
using System;
using System.Configuration;
using System.IO;
using WWTWebservices;

namespace WWT.Providers
{
public class DSSProvider : RequestProvider
{
public override void Run(WwtContext context)
private readonly IPlateTilePyramid _plateTile;

public DSSProvider(IPlateTilePyramid plateTile)
{
string wwtTilesDir = ConfigurationManager.AppSettings["WWTTilesDir"];
string dssTerapixelDir = ConfigurationManager.AppSettings["DssTerapixelDir"];
_plateTile = plateTile;
}

public override void Run(WwtContext context)
{
string query = context.Request.Params["Q"];
string[] values = query.Split(',');
int level = Convert.ToInt32(values[0]);
int tileX = Convert.ToInt32(values[1]);
int tileY = Convert.ToInt32(values[2]);

int octsetlevel = level;
string filename;


if (level > 12)
{
context.Response.Write("No image");
context.Response.Close();
return;
}

if (level < 8)
else if (level < 8)
{
string wwtTilesDir = ConfigurationManager.AppSettings["WWTTilesDir"];

context.Response.ContentType = "image/png";
Stream s = PlateTilePyramid.GetFileStream(wwtTilesDir + "\\dssterrapixel.plate", level, tileX, tileY);
int length = (int)s.Length;
byte[] data = new byte[length];
s.Read(data, 0, length);
context.Response.OutputStream.Write(data, 0, length);
context.Response.Flush();
context.Response.End();
return;

using (var s = _plateTile.GetStream(wwtTilesDir, "dssterrapixel.plate", level, tileX, tileY))
{
s.CopyTo(context.Response.OutputStream);
context.Response.Flush();
context.Response.End();
}
}
else
{
int L = level;
int X = tileX;
int Y = tileY;
string mime = "png";
int powLev5Diff = (int)Math.Pow(2, L - 5);
int X32 = X / powLev5Diff;
int Y32 = Y / powLev5Diff;
filename = string.Format(dssTerapixelDir + @"\DSS{0}L5to12_x{1}_y{2}.plate", mime, X32, Y32);
int powLev5Diff = (int)Math.Pow(2, level - 5);
int X32 = tileX / powLev5Diff;
int Y32 = tileY / powLev5Diff;

int L5 = level - 5;
int X5 = tileX % powLev5Diff;
int Y5 = tileY % powLev5Diff;

int L5 = L - 5;
int X5 = X % powLev5Diff;
int Y5 = Y % powLev5Diff;
context.Response.ContentType = "image/png";
Stream s = PlateTilePyramid.GetFileStream(filename, L5, X5, Y5);
int length = (int)s.Length;
byte[] data = new byte[length];
s.Read(data, 0, length);
context.Response.OutputStream.Write(data, 0, length);
context.Response.Flush();
context.Response.End();
return;

string dssTerapixelDir = ConfigurationManager.AppSettings["DssTerapixelDir"];
string filename = $"DSSpngL5to12_x{X32}_y{Y32}.plate";

using (var s = _plateTile.GetStream(dssTerapixelDir, filename, L5, X5, Y5))
{
s.CopyTo(context.Response.OutputStream);
context.Response.Flush();
context.Response.End();
}
}
}
}
Expand Down

0 comments on commit 54c4778

Please sign in to comment.