Skip to main content

Reference Library

Go Search
Reference Library
  
Reference Library > Wiki Pages > Server Map Caching  

Server Map Caching

Overview
An interface (IMapCacheManager) has been provided in the Core.Services namespace for developers to add caching to the map web service. Map requests on the server are hashed (using an MD5 hash) to create a unique cache key. Any changes to extents, symbology, etc. in a map request results in a different key. If an implementation of IMapCacheManager exists in the App_Code folder of the MDNS Web Service, and the appropriate entry has been added to the web.config, then the code is compiled on-the-fly and the cache will be used. The following interface must be implemented to support server-side caching:
    ...
 
namespace ISC.MapDotNetServer.Core.Services
{
    public interface IMapCacheManager
    {
        /// <summary>
        /// Read a MapResponse from cache based on the supplied cache-key.
        /// </summary>
        /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
        /// <param name="mapResponse">Serialized map response object to read.</param>
        /// <param name="cacheInfo">Cache information.</param>
        void ReadFromCache(string cacheKey, out string mapResponseSerial, out CacheInfo cacheInfo);

        /// <summary>
        /// Peek into the cache and just get information about it.
        /// </summary>
        /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
        /// <returns>Cache information.</returns>
        CacheInfo LookIntoCache(string cacheKey);

        /// <summary>
        /// Delete an entry in the cache by cache-key.
        /// </summary>
        /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
        void DeleteFromCache(string cacheKey);

        /// <summary>
        /// Write (Insert/Update) an entry in the cache based on the supplied cache-key.
        /// </summary>
        /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
        /// <param name="mapResponseSerial">Serialized map response object to save.</param>
        void WriteToCache(string cacheKey, string mapResponseSerial);
    }
}
 
web.config entries to enable caching
<add key="EnableMapCaching" value="false"/>
<add key="MapCacheManagerClassName" value="InProcMapCache"/>
 
    ...
 
Included in the installation of 6.5 is an example (part of app_code.dll - source not included):
The example below simply stores up to 100 map requests in your web service application process and manages the maximum in a "most-used" approach. You can use the source below to determine how you might implement your own cache more suitable for an enterprise solution such as RDBMS store.
 
/*
Copyright © 2008 – Specialized Technology Products, Inc. All Rights Reserved.
Product: MapDotNet Server
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using ISC.MapDotNetServer.Core.Services;
 
/// <summary>
/// Summary description for SessionMapCache
/// </summary>
public class InProcMapCache : IMapCacheManager
{
    #region DATA
    private const int kMaxCacheItems = 100;
    /// <summary>
    /// App-domain sorted list of cache items
    /// </summary>
    protected SortedList<string, CacheItem> Cache
    {
        get
        {
            if (_Cache == null)
            {
                _Cache = new SortedList<string, CacheItem>(kMaxCacheItems);
            }
            return _Cache;
        }
    }
    private volatile static SortedList<string, CacheItem> _Cache;
 
    // define cache item
    public class CacheItem
    {
        public string Data;
        public CacheInfo CacheInfo;
    }
 
    #endregion
    #region ICacheManager Members
 
    /// <summary>
    /// Read a MapResponse from cache based on the supplied cache-key.
    /// </summary>
    /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
    /// <param name="mapResponse">Serialized map response object to read.</param>
    /// <param name="cacheInfo">Cache information.</param>
    public void ReadFromCache(string cacheKey, out string mapResponseSerial, out CacheInfo cacheInfo)
    {
        lock (Cache)
        {
            if (Cache.ContainsKey(cacheKey))
            {
                CacheItem item = Cache[cacheKey];
                item.CacheInfo.ReadCount++;
                cacheInfo = item.CacheInfo;
                mapResponseSerial = item.Data;
            }
            else
            {
                cacheInfo = new CacheInfo();
                cacheInfo.Exist = false;
                mapResponseSerial = null;
            }
        }
    }

    /// <summary>
    /// Peek into the cache and just get information about it.
    /// </summary>
    /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
    /// <returns>Cache information.</returns>
    public CacheInfo LookIntoCache(string cacheKey)
    {
        lock (Cache)
        {
            if (Cache.ContainsKey(cacheKey))
            {
                CacheItem item = Cache[cacheKey];
                return item.CacheInfo;
            }
            else
            {
                CacheInfo ci = new CacheInfo();
                ci.Exist = false;
                return ci;
            }
        }
    }

    /// <summary>
    /// Delete an entry in the cache by cache-key.
    /// </summary>
    /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
    public void DeleteFromCache(string cacheKey)
    {
        lock (Cache)
        {
            if (Cache.ContainsKey(cacheKey))
            {
                Cache.Remove(cacheKey);
            }
        }
    }

    /// <summary>
    /// Write (Insert/Update) an entry in the cache based on the supplied cache-key.
    /// </summary>
    /// <param name="cacheKey">Cache-key - an MD5 hash of a MapRequest.</param>
    /// <param name="mapResponseSerial">Serialized map response object to save.</param>
    public void WriteToCache(string cacheKey, string mapResponseSerial)
    {
        if (!string.IsNullOrEmpty(cacheKey) && !string.IsNullOrEmpty(mapResponseSerial))
        {
            lock (Cache)
            {
                // check current cache capacity
                // remove the least desirable item
                if (Cache.Count >= kMaxCacheItems)
                {
                    // iterate and find the best item to remove
                    int oldestIdx = 0;
                    double staleFactor = -1.0;
                    for (int idx = 0; idx < Cache.Count; idx++)
                    {
                        CacheItem item = Cache.Values[idx];
                        // compute the stale-factor for each item
                        // this is based on the number of acccesses per unit time
                        double sf = Convert.ToDouble(item.CacheInfo.ReadCount + 1) /
                            Convert.ToDouble((DateTime.Now - item.CacheInfo.WriteDateTime).Seconds);
                        if (staleFactor < 0.0 || sf < staleFactor)
                        {
                            staleFactor = sf;
                            oldestIdx = idx;
                        }
                    }
                    Cache.RemoveAt(oldestIdx);
                }
                // insert new item
                CacheItem newItem = new CacheItem();
                newItem.CacheInfo = new CacheInfo();
                newItem.CacheInfo.Exist = true;
                newItem.CacheInfo.ReadCount = 0;
                newItem.CacheInfo.WriteDateTime = DateTime.Now;
                newItem.Data = mapResponseSerial;
                Cache[cacheKey] = newItem;
            }
        }
    }
    #endregion
}

Last modified at 11/11/2008 6:12 PM  by WEB\mark