diff --git a/Caching/FileDbCache.WPF/FileDbCache.cs b/Caching/FileDbCache.WPF/FileDbCache.cs index 03c8c761..20e9dcbc 100644 --- a/Caching/FileDbCache.WPF/FileDbCache.cs +++ b/Caching/FileDbCache.WPF/FileDbCache.cs @@ -81,7 +81,7 @@ namespace MapControl.Caching try { fileDb.Open(path, false); - Debug.WriteLine("FileDbCache: Opened database with {0} cached items in {1}.", fileDb.NumRecords, path); + Debug.WriteLine("FileDbCache: Opened database with {0} cached items in {1}", fileDb.NumRecords, path); Clean(); } @@ -146,7 +146,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.NumRecords failed: {0}", (object)ex.Message); + Debug.WriteLine("FileDbCache: FileDb.NumRecords: " + ex.Message); } } @@ -173,7 +173,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\"): {1}", key, ex.Message); } } @@ -205,7 +205,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\"): {1}", key, ex.Message); } } @@ -248,20 +248,20 @@ namespace MapControl.Caching if (fileDb.IsOpen) { - var expires = DateTime.MaxValue; + var expiration = DateTime.MaxValue; if (policy.AbsoluteExpiration != InfiniteAbsoluteExpiration) { - expires = policy.AbsoluteExpiration.DateTime; + expiration = policy.AbsoluteExpiration.DateTime; } else if (policy.SlidingExpiration != NoSlidingExpiration) { - expires = DateTime.UtcNow + policy.SlidingExpiration; + expiration = DateTime.UtcNow + policy.SlidingExpiration; } - if (!AddOrUpdateRecord(key, value, expires) && RepairDatabase()) + if (!AddOrUpdateRecord(key, value, expiration) && RepairDatabase()) { - AddOrUpdateRecord(key, value, expires); + AddOrUpdateRecord(key, value, expiration); } } } @@ -311,7 +311,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.DeleteRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.DeleteRecordByKey(\"{0}\"): {1}", key, ex.Message); } } @@ -335,11 +335,11 @@ namespace MapControl.Caching { if (fileDb.IsOpen) { - fileDb.DeleteRecords(new FilterExpression(expiresField, DateTime.UtcNow, ComparisonOperatorEnum.LessThan)); + int deleted = fileDb.DeleteRecords(new FilterExpression(expiresField, DateTime.UtcNow, ComparisonOperatorEnum.LessThan)); - if (fileDb.NumDeleted > 0) + if (deleted > 0) { - Debug.WriteLine("FileDbCache: Deleted {0} expired items.", fileDb.NumDeleted); + Debug.WriteLine("FileDbCache: Deleted {0} expired items", deleted); fileDb.Clean(); } } @@ -373,7 +373,7 @@ namespace MapControl.Caching new Field(expiresField, DataTypeEnum.DateTime) }); - Debug.WriteLine("FileDbCache: Created database {0}.", (object)path); + Debug.WriteLine("FileDbCache: Created database " + path); } private bool RepairDatabase() @@ -385,7 +385,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.Reindex() failed: {0}", (object)ex.Message); + Debug.WriteLine("FileDbCache: FileDb.Reindex(): " + ex.Message); } try @@ -395,17 +395,17 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: Creating database {0} failed: {1}", path, ex.Message); + Debug.WriteLine("FileDbCache: Creating database {0}: {1}", path, ex.Message); } return false; } - private bool AddOrUpdateRecord(string key, object value, DateTime expires) + private bool AddOrUpdateRecord(string key, object value, DateTime expiration) { var fieldValues = new FieldValues(3); fieldValues.Add(valueField, value); - fieldValues.Add(expiresField, expires); + fieldValues.Add(expiresField, expiration); bool recordExists; @@ -415,7 +415,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\"): {1}", key, ex.Message); return false; } @@ -427,7 +427,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.UpdateRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.UpdateRecordByKey(\"{0}\"): {1}", key, ex.Message); return false; } } @@ -440,11 +440,12 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.AddRecord(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.AddRecord(\"{0}\"): {1}", key, ex.Message); return false; } } + //Debug.WriteLine("FileDbCache: Writing \"{0}\", Expires {1}", key, expiration.ToLocalTime()); return true; } } diff --git a/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs b/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs index a61ba671..b8bb9509 100644 --- a/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs +++ b/Caching/FileDbCache.WPF/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/Caching/FileDbCache.WinRT/FileDbCache.cs b/Caching/FileDbCache.WinRT/FileDbCache.cs index 8e2d62e3..0289ad02 100644 --- a/Caching/FileDbCache.WinRT/FileDbCache.cs +++ b/Caching/FileDbCache.WinRT/FileDbCache.cs @@ -63,11 +63,11 @@ namespace MapControl.Caching { if (fileDb.IsOpen) { - fileDb.DeleteRecords(new FilterExpression(expiresField, DateTime.UtcNow, ComparisonOperatorEnum.LessThan)); + int deleted = fileDb.DeleteRecords(new FilterExpression(expiresField, DateTime.UtcNow, ComparisonOperatorEnum.LessThan)); - if (fileDb.NumDeleted > 0) + if (deleted > 0) { - Debug.WriteLine("FileDbCache: Deleted {0} expired items.", fileDb.NumDeleted); + Debug.WriteLine("FileDbCache: Deleted {0} expired items", deleted); fileDb.Clean(); } } @@ -88,7 +88,7 @@ namespace MapControl.Caching return await Task.Run(() => Get(key)); } - public async Task SetAsync(string key, IBuffer buffer, DateTime expires) + public async Task SetAsync(string key, IBuffer buffer, DateTime expiration) { if (key == null) { @@ -103,11 +103,11 @@ namespace MapControl.Caching if (fileDb.IsOpen) { var bytes = buffer.ToArray(); - var ok = await Task.Run(() => AddOrUpdateRecord(key, bytes, expires)); + var ok = await Task.Run(() => AddOrUpdateRecord(key, bytes, expiration)); if (!ok && (await RepairDatabase())) { - await Task.Run(() => AddOrUpdateRecord(key, bytes, expires)); + await Task.Run(() => AddOrUpdateRecord(key, bytes, expiration)); } } } @@ -122,7 +122,7 @@ namespace MapControl.Caching var stream = await file.OpenAsync(FileAccessMode.ReadWrite); fileDb.Open(stream.AsStream()); - Debug.WriteLine("FileDbCache: Opened database with {0} cached items in {1}.", fileDb.NumRecords, file.Path); + Debug.WriteLine("FileDbCache: Opened database with {0} cached items in {1}", fileDb.NumRecords, file.Path); Clean(); return; @@ -157,7 +157,7 @@ namespace MapControl.Caching new Field(expiresField, DataTypeEnum.DateTime) }); - Debug.WriteLine("FileDbCache: Created database {0}.", file.Path); + Debug.WriteLine("FileDbCache: Created database " + file.Path); } private async Task RepairDatabase() @@ -169,7 +169,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.Reindex() failed: {0}", ex.Message); + Debug.WriteLine("FileDbCache: FileDb.Reindex(): " + ex.Message); } try @@ -179,7 +179,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: Creating database {0} failed: {1}", Path.Combine(folder.Path, name), ex.Message); + Debug.WriteLine("FileDbCache: Creating database {0}: {1}", Path.Combine(folder.Path, name), ex.Message); } return false; @@ -188,50 +188,33 @@ namespace MapControl.Caching private ImageCacheItem Get(string key) { var fields = new string[] { valueField, expiresField }; - Record record = null; try { - record = fileDb.GetRecordByKey(key, fields, false); - } - catch (Exception ex) - { - Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\") failed: {1}", key, ex.Message); - } + var record = fileDb.GetRecordByKey(key, fields, false); - if (record != null) - { - try + if (record != null) { return new ImageCacheItem { Buffer = ((byte[])record[0]).AsBuffer(), - Expires = (DateTime)record[1] + Expiration = (DateTime)record[1] }; } - catch (Exception ex) - { - Debug.WriteLine("FileDbCache: Decoding \"{0}\" failed: {1}", key, ex.Message); - } - - try - { - fileDb.DeleteRecordByKey(key); - } - catch (Exception ex) - { - Debug.WriteLine("FileDbCache: FileDb.DeleteRecordByKey(\"{0}\") failed: {1}", key, ex.Message); - } + } + catch (Exception ex) + { + Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\"): {1}", key, ex.Message); } return null; } - private bool AddOrUpdateRecord(string key, byte[] value, DateTime expires) + private bool AddOrUpdateRecord(string key, byte[] value, DateTime expiration) { var fieldValues = new FieldValues(3); fieldValues.Add(valueField, value); - fieldValues.Add(expiresField, expires); + fieldValues.Add(expiresField, expiration); bool recordExists; @@ -241,7 +224,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.GetRecordByKey(\"{0}\"): {1}", key, ex.Message); return false; } @@ -253,7 +236,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.UpdateRecordByKey(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.UpdateRecordByKey(\"{0}\"): {1}", key, ex.Message); return false; } } @@ -266,12 +249,12 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("FileDbCache: FileDb.AddRecord(\"{0}\") failed: {1}", key, ex.Message); + Debug.WriteLine("FileDbCache: FileDb.AddRecord(\"{0}\"): {1}", key, ex.Message); return false; } } - //Debug.WriteLine("Cached item {0}, expires {1}", key, expires); + //Debug.WriteLine("FileDbCache: Writing \"{0}\", Expires {1}", key, expiration.ToLocalTime()); return true; } } diff --git a/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs b/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs index 103245ae..9c601c38 100644 --- a/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs +++ b/Caching/FileDbCache.WinRT/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/Caching/ImageFileCache.WPF/ImageFileCache.cs b/Caching/ImageFileCache.WPF/ImageFileCache.cs index 627a5cb3..04109a25 100644 --- a/Caching/ImageFileCache.WPF/ImageFileCache.cs +++ b/Caching/ImageFileCache.WPF/ImageFileCache.cs @@ -22,13 +22,12 @@ namespace MapControl.Caching { private static readonly Tuple[] imageFileTypes = new Tuple[] { - new Tuple(".png", new byte[] { 0x89, 0x50, 0x4E, 0x47, 0xD, 0xA, 0x1A, 0xA }), - new Tuple(".jpg", new byte[] { 0xFF, 0xD8, 0xFF, 0xE0, 0, 0x10, 0x4A, 0x46, 0x49, 0x46, 0 }), + new Tuple(".png", new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }), + new Tuple(".jpg", new byte[] { 0xFF, 0xD8, 0xFF }), new Tuple(".bmp", new byte[] { 0x42, 0x4D }), new Tuple(".gif", new byte[] { 0x47, 0x49, 0x46 }), - new Tuple(".tif", new byte[] { 0x49, 0x49, 42, 0 }), - new Tuple(".tif", new byte[] { 0x4D, 0x4D, 0, 42 }), - new Tuple(".wdp", new byte[] { 0x49, 0x49, 0xBC }), + new Tuple(".tif", new byte[] { 0x49, 0x49, 0x2A, 0x00 }), + new Tuple(".tif", new byte[] { 0x4D, 0x4D, 0x00, 0x2A }), new Tuple(".bin", new byte[] { }), }; @@ -61,7 +60,7 @@ namespace MapControl.Caching rootFolder = Path.Combine(folder, name); Directory.CreateDirectory(rootFolder); - Debug.WriteLine("Created ImageFileCache in {0}.", (object)rootFolder); + Debug.WriteLine("Created ImageFileCache in " + rootFolder); } public override string Name @@ -132,12 +131,13 @@ namespace MapControl.Caching { try { + //Debug.WriteLine("ImageFileCache: Reading " + path); buffer = File.ReadAllBytes(path); memoryCache.Set(key, buffer, new CacheItemPolicy()); } catch (Exception ex) { - Debug.WriteLine("ImageFileCache: Writing file {0} failed: {1}", path, ex.Message); + Debug.WriteLine("ImageFileCache: Reading {0}: {1}", path, ex.Message); } } } @@ -183,6 +183,7 @@ namespace MapControl.Caching try { + //Debug.WriteLine("ImageFileCache: Writing {0}, Expires {1}", path, policy.AbsoluteExpiration.DateTime.ToLocalTime()); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllBytes(path, buffer); @@ -192,7 +193,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("ImageFileCache: Writing file {0} failed: {1}", path, ex.Message); + Debug.WriteLine("ImageFileCache: Writing {0}: {1}", path, ex.Message); } } @@ -253,7 +254,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("ImageFileCache: Removing file {0} failed: {1}", path, ex.Message); + Debug.WriteLine("ImageFileCache: Removing {0}: {1}", path, ex.Message); } } @@ -280,7 +281,7 @@ namespace MapControl.Caching } catch (Exception ex) { - Debug.WriteLine("ImageFileCache: Finding file {0} failed: {1}", path, ex.Message); + Debug.WriteLine("ImageFileCache: Finding {0}: {1}", path, ex.Message); } return null; diff --git a/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs b/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs index 943d8964..2cf9bcf7 100644 --- a/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs +++ b/Caching/ImageFileCache.WPF/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/Caching/ImageFileCache.WinRT/ImageFileCache.cs b/Caching/ImageFileCache.WinRT/ImageFileCache.cs index dc2d6b8e..844f87da 100644 --- a/Caching/ImageFileCache.WinRT/ImageFileCache.cs +++ b/Caching/ImageFileCache.WinRT/ImageFileCache.cs @@ -32,7 +32,7 @@ namespace MapControl.Caching folder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists).Completed = (o, s) => { rootFolder = o.GetResults(); - Debug.WriteLine("Created ImageFileCache in {0}.", rootFolder.Path); + Debug.WriteLine("Created ImageFileCache in " + rootFolder.Path); }; } @@ -43,26 +43,26 @@ namespace MapControl.Caching if (item != null && item.IsOfType(StorageItemTypes.File)) { var file = (StorageFile)item; - //Debug.WriteLine("ImageFileCache: Reading file {0}", file.Path); + //Debug.WriteLine("ImageFileCache: Reading " + file.Path); try { return new ImageCacheItem { Buffer = await FileIO.ReadBufferAsync(file), - Expires = (await file.Properties.GetImagePropertiesAsync()).DateTaken.UtcDateTime + Expiration = (await file.Properties.GetImagePropertiesAsync()).DateTaken.UtcDateTime }; } catch (Exception ex) { - Debug.WriteLine("ImageFileCache: Reading file {0} failed: {1}", file.Path, ex.Message); + Debug.WriteLine("ImageFileCache: Reading {0}: {1}", file.Path, ex.Message); } } return null; } - public virtual async Task SetAsync(string key, IBuffer buffer, DateTime expires) + public virtual async Task SetAsync(string key, IBuffer buffer, DateTime expiration) { try { @@ -75,18 +75,18 @@ namespace MapControl.Caching } var file = await folder.CreateFileAsync(names[names.Length - 1], CreationCollisionOption.ReplaceExisting); - //Debug.WriteLine("ImageFileCache: Writing file {0}", file.Path); + //Debug.WriteLine("ImageFileCache: Writing {0}, Expires {1}", file.Path, expiration.ToLocalTime()); await FileIO.WriteBufferAsync(file, buffer); // Store expiration date in ImageProperties.DateTaken var properties = await file.Properties.GetImagePropertiesAsync(); - properties.DateTaken = expires; + properties.DateTaken = expiration; await properties.SavePropertiesAsync(); } catch (Exception ex) { - Debug.WriteLine("ImageFileCache: Writing file {0}\\{1} failed: {2}", rootFolder.Path, key, ex.Message); + Debug.WriteLine("ImageFileCache: Writing {0}\\{1}: {2}", rootFolder.Path, key, ex.Message); } } } diff --git a/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs b/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs index 0f9bdc17..19b7f368 100644 --- a/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs +++ b/Caching/ImageFileCache.WinRT/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MapControl/ImageCache.WinRT.cs b/MapControl/ImageCache.WinRT.cs index f74912c7..55cb3959 100644 --- a/MapControl/ImageCache.WinRT.cs +++ b/MapControl/ImageCache.WinRT.cs @@ -11,12 +11,12 @@ namespace MapControl.Caching public class ImageCacheItem { public IBuffer Buffer { get; set; } - public DateTime Expires { get; set; } + public DateTime Expiration { get; set; } } public interface IImageCache { Task GetAsync(string key); - Task SetAsync(string key, IBuffer buffer, DateTime expires); + Task SetAsync(string key, IBuffer buffer, DateTime expiration); } } diff --git a/MapControl/Properties/AssemblyInfo.cs b/MapControl/Properties/AssemblyInfo.cs index 2ff000c3..0e6f39eb 100644 --- a/MapControl/Properties/AssemblyInfo.cs +++ b/MapControl/Properties/AssemblyInfo.cs @@ -14,8 +14,8 @@ using System.Windows; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MapControl/TileImageLoader.WPF.cs b/MapControl/TileImageLoader.WPF.cs index 4bbfc635..0a38a748 100644 --- a/MapControl/TileImageLoader.WPF.cs +++ b/MapControl/TileImageLoader.WPF.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -38,11 +37,16 @@ namespace MapControl /// /// Default expiration time for cached tile images. Used when no expiration time - /// was transmitted on download. The default and recommended minimum value is seven days. - /// See OpenStreetMap tile usage policy: http://wiki.openstreetmap.org/wiki/Tile_usage_policy + /// was transmitted on download. The default value is one day. /// public static TimeSpan DefaultCacheExpiration { get; set; } + /// + /// Minimum expiration time for cached tile images. Used when an unnecessarily small expiration time + /// was transmitted on download (e.g. Cache-Control: max-age=0). The default value is one hour. + /// + public static TimeSpan MinimumCacheExpiration { get; set; } + /// /// The ObjectCache used to cache tile images. The default is MemoryCache.Default. /// @@ -55,7 +59,8 @@ namespace MapControl static TileImageLoader() { - DefaultCacheExpiration = TimeSpan.FromDays(7); + DefaultCacheExpiration = TimeSpan.FromDays(1); + MinimumCacheExpiration = TimeSpan.FromHours(1); Cache = MemoryCache.Default; } @@ -198,7 +203,7 @@ namespace MapControl } catch (Exception ex) { - Debug.WriteLine("ImageTileSource.LoadImage: " + ex.Message); + Debug.WriteLine(ex.Message); } return image; @@ -318,37 +323,33 @@ namespace MapControl memoryStream.Write(BitConverter.GetBytes(expiration.Ticks), 0, 8); Cache.Set(cacheKey, memoryStream.ToArray(), new CacheItemPolicy { AbsoluteExpiration = expiration }); - - //Debug.WriteLine("Cached {0}, Expires {1}", cacheKey, expiration); } private static DateTime GetExpiration(WebHeaderCollection headers) { + var expiration = DefaultCacheExpiration; var cacheControl = headers["Cache-Control"]; - int maxAge; - DateTime expiration; - if (cacheControl != null && - cacheControl.StartsWith("max-age=") && - int.TryParse(cacheControl.Substring(8), out maxAge)) + if (cacheControl != null) { - maxAge = Math.Min(maxAge, (int)DefaultCacheExpiration.TotalSeconds); - expiration = DateTime.UtcNow.AddSeconds(maxAge); - } - else - { - var expires = headers["Expires"]; - var maxExpiration = DateTime.UtcNow.Add(DefaultCacheExpiration); + int maxAgeValue; + var maxAgeDirective = cacheControl + .Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) + .FirstOrDefault(s => s.StartsWith("max-age=")); - if (expires == null || - !DateTime.TryParse(expires, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out expiration) || - expiration > maxExpiration) + if (maxAgeDirective != null && + int.TryParse(maxAgeDirective.Substring(8), out maxAgeValue)) { - expiration = maxExpiration; + expiration = TimeSpan.FromSeconds(maxAgeValue); + + if (expiration < MinimumCacheExpiration) + { + expiration = MinimumCacheExpiration; + } } } - return expiration; + return DateTime.UtcNow.Add(expiration); } } } diff --git a/MapControl/TileImageLoader.WinRT.cs b/MapControl/TileImageLoader.WinRT.cs index 13d45d16..77a6086c 100644 --- a/MapControl/TileImageLoader.WinRT.cs +++ b/MapControl/TileImageLoader.WinRT.cs @@ -35,11 +35,16 @@ namespace MapControl /// /// Default expiration time for cached tile images. Used when no expiration time - /// was transmitted on download. The default and recommended minimum value is seven days. - /// See OpenStreetMap tile usage policy: http://wiki.openstreetmap.org/wiki/Tile_usage_policy + /// was transmitted on download. The default value is one day. /// public static TimeSpan DefaultCacheExpiration { get; set; } + /// + /// Minimum expiration time for cached tile images. Used when an unnecessarily small expiration time + /// was transmitted on download (e.g. Cache-Control: max-age=0). The default value is one hour. + /// + public static TimeSpan MinimumCacheExpiration { get; set; } + /// /// The IImageCache implementation used to cache tile images. The default is null. /// @@ -47,7 +52,8 @@ namespace MapControl static TileImageLoader() { - DefaultCacheExpiration = TimeSpan.FromDays(7); + DefaultCacheExpiration = TimeSpan.FromDays(1); + MinimumCacheExpiration = TimeSpan.FromHours(1); } private class PendingTile @@ -102,7 +108,7 @@ namespace MapControl } catch (Exception ex) { - Debug.WriteLine("Loading tile image failed: {0}", ex.Message); + Debug.WriteLine(ex.Message); } var newTaskCount = Math.Min(pendingTiles.Count, tileLayer.MaxParallelDownloads) - taskCount; @@ -143,7 +149,7 @@ namespace MapControl var cacheItem = await Cache.GetAsync(cacheKey); var loaded = false; - if (cacheItem == null || cacheItem.Expires <= DateTime.UtcNow) + if (cacheItem == null || cacheItem.Expiration <= DateTime.UtcNow) { loaded = await DownloadImage(tile, image, uri, cacheKey); } @@ -176,7 +182,7 @@ namespace MapControl return await LoadImageFromHttpResponse(response, tile, image, cacheKey); } - Debug.WriteLine("{0}: ({1}) {2}", uri, (int)response.StatusCode, response.ReasonPhrase); + Debug.WriteLine("{0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); } } catch (Exception ex) @@ -208,15 +214,19 @@ namespace MapControl stream.Seek(0); await stream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None); - var maxAge = DefaultCacheExpiration; + var expiration = DefaultCacheExpiration; - if (response.Headers.CacheControl.MaxAge.HasValue && - response.Headers.CacheControl.MaxAge.Value < maxAge) + if (response.Headers.CacheControl.MaxAge.HasValue) { - maxAge = response.Headers.CacheControl.MaxAge.Value; + expiration = response.Headers.CacheControl.MaxAge.Value; + + if (expiration < MinimumCacheExpiration) + { + expiration = MinimumCacheExpiration; + } } - await Cache.SetAsync(cacheKey, buffer, DateTime.UtcNow.Add(maxAge)); + await Cache.SetAsync(cacheKey, buffer, DateTime.UtcNow.Add(expiration)); } return loaded; @@ -235,14 +245,12 @@ namespace MapControl { await image.SetSourceAsync(stream); tile.SetImage(image, true, false); - completion.SetResult(true); } catch (Exception ex) { Debug.WriteLine(ex.Message); tile.SetImage(null); - completion.SetResult(false); } }); diff --git a/MapControl/WinRT/Properties/AssemblyInfo.cs b/MapControl/WinRT/Properties/AssemblyInfo.cs index f7a0b7bc..751333e4 100644 --- a/MapControl/WinRT/Properties/AssemblyInfo.cs +++ b/MapControl/WinRT/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs b/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs index 0e9afe16..82adfbbb 100644 --- a/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs +++ b/SampleApps/PhoneApplication/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs b/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs index d17eed8a..4e69e703 100644 --- a/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs +++ b/SampleApps/SilverlightApplication.Web/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs b/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs index 41917307..27fac4fb 100644 --- a/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs +++ b/SampleApps/SilverlightApplication/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/SampleApps/StoreApplication/Properties/AssemblyInfo.cs b/SampleApps/StoreApplication/Properties/AssemblyInfo.cs index 6d2d925a..2e653e23 100644 --- a/SampleApps/StoreApplication/Properties/AssemblyInfo.cs +++ b/SampleApps/StoreApplication/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: ComVisible(false)] diff --git a/SampleApps/UniversalApp/Properties/AssemblyInfo.cs b/SampleApps/UniversalApp/Properties/AssemblyInfo.cs index 9880050f..6b783c9d 100644 --- a/SampleApps/UniversalApp/Properties/AssemblyInfo.cs +++ b/SampleApps/UniversalApp/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: ComVisible(false)] diff --git a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs index c7f56aa3..686afc32 100644 --- a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs +++ b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ using System.Runtime.InteropServices; [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("2.7.0")] -[assembly: AssemblyFileVersion("2.7.0")] +[assembly: AssemblyVersion("2.7.1")] +[assembly: AssemblyFileVersion("2.7.1")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)]