11using System ;
2- using System . Collections . Concurrent ;
32using System . IO ;
43using System . IO . MemoryMappedFiles ;
54using System . Linq ;
65using System . Threading . Tasks ;
6+ using LazyCache ;
77using Microsoft . AspNetCore . Hosting ;
8+ using Microsoft . Extensions . Caching . Memory ;
89using Microsoft . Extensions . FileProviders ;
910using Microsoft . Extensions . Logging ;
1011using NetTopologySuite . Geometries ;
@@ -20,18 +21,22 @@ public class MemoryMapElevationProvider : IElevationProvider
2021 {
2122 private readonly ILogger < MemoryMapElevationProvider > _logger ;
2223 private readonly IFileProvider _fileProvider ;
23- private readonly ConcurrentDictionary < Coordinate , Task < FileAndSamples > > _mappedFilesCache ;
24+ private readonly IAppCache _appCache ;
25+ private readonly int _cacheSlidingWindowTimeInMinutes ;
2426
2527 /// <summary>
2628 /// Constructor
2729 /// </summary>
2830 /// <param name="webHostEnvironment"></param>
2931 /// <param name="logger"></param>
30- public MemoryMapElevationProvider ( IWebHostEnvironment webHostEnvironment , ILogger < MemoryMapElevationProvider > logger )
32+ /// <param name="appCache"></param>
33+ public MemoryMapElevationProvider ( IWebHostEnvironment webHostEnvironment , ILogger < MemoryMapElevationProvider > logger , IAppCache appCache )
3134 {
3235 _logger = logger ;
36+ _appCache = appCache ;
3337 _fileProvider = webHostEnvironment . ContentRootFileProvider ;
34- _mappedFilesCache = new ( ) ;
38+ var cacheSlidingWindow = Environment . GetEnvironmentVariable ( "CACHE_SLIDING_WINDOW" ) ;
39+ _cacheSlidingWindowTimeInMinutes = string . IsNullOrWhiteSpace ( cacheSlidingWindow ) ? 30 : int . Parse ( cacheSlidingWindow ) ;
3540 }
3641
3742 /// <summary>
@@ -54,19 +59,31 @@ public Task<double[]> GetElevation(double[][] latLngs)
5459 var tasks = latLngs . Select ( async latLng =>
5560 {
5661 var key = new Coordinate ( Math . Floor ( latLng [ 0 ] ) , Math . Floor ( latLng [ 1 ] ) ) ;
57- if ( ! _mappedFilesCache . ContainsKey ( key ) )
62+ var info = await _appCache . GetOrAddAsync ( key . ToString ( ) , ( ) =>
5863 {
59- var filePath = Path . Join ( ElevationHelper . ELEVATION_CACHE , ElevationHelper . KeyToFileName ( key ) ) ;
60- var fileInfo = _fileProvider . GetFileInfo ( filePath ) ;
61- if ( ! fileInfo . Exists )
64+ return Task . Run ( ( ) =>
6265 {
63- return 0 ;
64- }
65- _logger . LogInformation ( $ "Loading { fileInfo . PhysicalPath } into memory mapped cache") ;
66- _mappedFilesCache [ key ] = Task . Run ( ( ) => new FileAndSamples ( MemoryMappedFile . CreateFromFile ( fileInfo . PhysicalPath ! , FileMode . Open ) , ElevationHelper . SamplesFromLength ( fileInfo . Length ) ) ) ;
67- }
68- var info = await _mappedFilesCache [ key ] ;
66+ var filePath = Path . Join ( ElevationHelper . ELEVATION_CACHE , ElevationHelper . KeyToFileName ( key ) ) ;
67+ var fileInfo = _fileProvider . GetFileInfo ( filePath ) ;
68+ if ( ! fileInfo . Exists )
69+ {
70+ _logger . LogWarning ( $ "Missing hgt file for { key } ") ;
71+ return new FileAndSamples ( null , 0 ) ;
72+ }
73+
74+ _logger . LogInformation ( $ "Loading { fileInfo . PhysicalPath } into memory mapped cache") ;
75+ return new FileAndSamples (
76+ MemoryMappedFile . CreateFromFile ( fileInfo . PhysicalPath ! , FileMode . Open ) ,
77+ ElevationHelper . SamplesFromLength ( fileInfo . Length ) ) ;
78+ } ) ;
79+
80+ } , TimeSpan . FromMinutes ( _cacheSlidingWindowTimeInMinutes ) ) ;
6981
82+ if ( info . File == null )
83+ {
84+ return 0 ;
85+ }
86+
7087 var exactLocation = new Coordinate ( Math . Abs ( latLng [ 0 ] - key . X ) * ( info . Samples - 1 ) ,
7188 ( 1 - Math . Abs ( latLng [ 1 ] - key . Y ) ) * ( info . Samples - 1 ) ) ;
7289
0 commit comments