Event for "max cache size"

May 22, 2009 at 2:35 PM

It would be great if one could specify the maximum cache size (e.g. 250 MB).

It it is reached, one of these things could happen:

- the next program closing should delete cache directory
- the control deletes "unused" tiles automatically
-an event is thrown
...

Deleting "unused" tiles automatically would be perfect, but I think its also the most complicated one.

 

Coordinator
May 22, 2009 at 2:38 PM
Edited May 22, 2009 at 2:38 PM

what is unused tiles? and why to limit cache to 200MB its allmost nothing

May 22, 2009 at 2:46 PM

"unused" means the oldest tiles (lowest "last access time").

200 MB is just am example. As I know that the cache-size is huge, I want to avoid that it is growing all over the time - without control.

Why not shrink it from time to time ?

 

Coordinator
May 22, 2009 at 2:48 PM

why not limit user browsing area instead?

May 23, 2009 at 11:49 AM

But I don't know where the user wants to browse. Or did I misunderstand you ?

Coordinator
May 23, 2009 at 1:17 PM

browsers are used for browsing ;}

May 23, 2009 at 1:27 PM

Well,

the web-browser has a build-it maximum memory border (temporary internet files). If this size is arrived, the system begins to delete old files - automatically.

Here the browsing is in a forms application, and the cache  is OUTSIDE the control of the temporary internet files.
So if the user browses all over the time - he is allowed to and it is good that he is doing so - the cache grows and grows. No control here. How many Gigabytes are ok?

If the user notices that there are some 10 GBytes of data just for cache anywhere in his application data folder, I think he will not agree with this. Thats the point.

Coordinator
May 23, 2009 at 3:53 PM

10GB would be allmost all world map in all zoom levels ;} it pretty hard to 'browse' that a lot of tiles, even 1GB is like europa on allmost all zoom levels

Coordinator
May 23, 2009 at 4:06 PM

anyway, if you want such option, you need to create new db provider which stores last access time to tile ...and that will slow loading down which is slow enough even now...

Jun 1, 2009 at 3:30 PM

I had created such functionality, but it is for build gmap4dotnet-30649... It's not working out of the box because of the old version it is made for, but if you want to see it...;-)

Coordinator
Jun 1, 2009 at 4:51 PM

sure ;}

Jun 1, 2009 at 6:00 PM

You can download a sample app (non GMap.NET) from here http://www.vbforums.com/attachment.php?attachmentid=69164&d=1234879918 . Then I made a few adjustements in GMap.NET, as a new property "public long MaxCacheSize", and with every updated file "Cache.Update(dir.ToString().Replace(Cache.RootFolder, ""), new FileInfo(dir.ToString()).Length, DateTime.Now);" etcetera.

If you like it, I have a few more details for you tomorrow ;-)

Coordinator
Jun 1, 2009 at 6:29 PM

sure ;}

Jun 2, 2009 at 4:23 PM
Edited Jun 2, 2009 at 4:26 PM

I had created a file which adjustements I had made in Gmap.NET for myself, but I had to translate it. This should be it.

  • Rename Cache.cs to CacheFunctions.cs
  • Add in CacheFunctions.cs, in "internal class Cache", this:
          public long MaxCacheSize
          {
              get
              {
                  return maxcachesize;
              }
              set
              {
                  maxcachesize = value;
              }
          }
  • Add in GMapControl.cs, in "#region -- properties --", this:
          /// <summary>
          /// Maximum cache size in bytes
          /// </summary>
          public long MaxCacheSize
          {
              get
              {
                  return Manager.Cache.MaxCacheSize;
              }
              set
              {
                  Manager.Cache.MaxCacheSize = value;
                  SafeInvalidate();
              }
          }
  • Replace in GoogleMaps.cs, in "public class GoogleMaps",
    "internal Cache Cache = new Cache();" to "public CacheFunctions Cache = new CacheFunctions();"
  • Replace in CacheFunctions.cs, "internal class Cache" to "public class CacheFunctions"
  • Create Cache.cs, with this code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
  • namespace GMapNET
    {
        [Serializable()]
        public class Cache
        {
  •         private List<CacheFile> _CacheFiles;
            public List<CacheFile> CacheFiles
            {
                get { return _CacheFiles; }
                set { _CacheFiles = value; }
            }
  •         private long _MaxSize;
            public long MaxSize
            {
                get { return _MaxSize; }
                set { _MaxSize = value; }
            }
  •         private string _RootFolder;
            public string RootFolder
            {
                get { return _RootFolder; }
                set { _RootFolder = value; }
            }
  •         private long _CacheSize;
            public long CacheSize
            {
                get { return _CacheSize; }
                set { _CacheSize = value; }
            }
  •         public void Add(string FileName, long FileSize, System.DateTime LastUsedDate)
            {
                _CacheFiles.Add(new CacheFile(FileName, FileSize, LastUsedDate));
                _CacheSize += FileSize;
            }
  •         public void Update(string FileName, long FileSize, System.DateTime LastUsedDate)
            {
                DeleteFile(FileName);
                Add(FileName, FileSize, LastUsedDate);
            }
  •         public void DeleteFile(string FileName)
            {
           
            CacheFile cf = default(CacheFile);
                foreach (CacheFile c in _CacheFiles)
                {
                    if(c.FileName == FileName) {
                        cf = c;
                        break;
                    }
                }
                //VB:  cf = (From c In _CacheFiles Where c.FileName = FileName).LastOrDefault
                //C#1: cf = from c in _CacheFiles where c.FileName = FileName select c;
                //C#2: cf = from CacheFile c in _CacheFiles where c.FileName = FileName select c;
           
            if ((cf != null)) {
                _CacheFiles.Remove(cf);
                _CacheSize -= cf.FileSize;
            }
           
        }
       
            public void Clear()
            {
                _CacheSize = 0;
                CacheFile cf = default(CacheFile);
                foreach (CacheFile c in _CacheFiles)
                {
                    _CacheFiles.Remove(c);
                }
            }
  •         public Cache()
            {
                _CacheFiles = new List<CacheFile>();
            }
        }
    }
  • Create CacheFile.cs with this code:
    using System;
    using System.Collections.Generic;
    using System.Text;
  • namespace GMapNET
    {
        [Serializable()]
        public class CacheFile
        {
  •         private string _FileName;
            public string FileName
            {
                get { return _FileName; }
                set { _FileName = value; }
            }

  •         private long _FileSize;
            public long FileSize
            {
                get { return _FileSize; }
                set { _FileSize = value; }
            }

  •         private System.DateTime _LastUsedDate;
            public System.DateTime LastUsedDate
            {
                get { return _LastUsedDate; }
                set { _LastUsedDate = value; }
            }

  •         public CacheFile(string File, long Size, System.DateTime LastUsed)
            {
                FileName = File;
                FileSize = Size;
                LastUsedDate = LastUsed;
            }
  •         public CacheFile()
            {
  •         }
        }
    }
  • In CacheFunctions.cs add this: (In "public class CacheFunctions")
          public CacheFunctions()
          {
              try
              {
                  XmlSerializer serializer = new XmlSerializer(typeof(Cache));
                  FileStream myFileStream = new FileStream(Application.StartupPath + "\\cache.xml", FileMode.Open);
                  Cache = (Cache)serializer.Deserialize(myFileStream);
                  myFileStream.Close();
              }
              catch
              {
              }
          }

    public void Serialize()
          {
              ComputeSize();
              StreamWriter string_writer = new StreamWriter(Application.StartupPath + "\\cache.xml");
              XmlSerializer serializer = new XmlSerializer(typeof(Cache));
              serializer.Serialize(string_writer, Cache);
              string_writer.Close();
          }
    public void ComputeSize()
          {
              if (Cache.CacheSize > Cache.MaxSize)
              {
                  Comparer dc = new Comparer();
                  Cache.CacheFiles.Sort(dc);
                  int i;
                  for (i = Cache.CacheFiles.Count - 1; i >= 0; i += -1)
                  {

                      if (Cache.CacheSize <= Cache.MaxSize) break;

                      if (File.Exists(Cache.RootFolder + Cache.CacheFiles[i].FileName)) File.Delete(Cache.RootFolder + Cache.CacheFiles[i].FileName);

                      if (Directory.Exists(GetParentPath(Cache.RootFolder + Cache.CacheFiles[i].FileName)))
                      {
                          if (Directory.GetFiles(GetParentPath(Cache.RootFolder + Cache.CacheFiles[i].FileName)).Length == 0) Directory.Delete(GetParentPath(Cache.RootFolder + Cache.CacheFiles[i].FileName));
                      }

                      Cache.DeleteFile(Cache.CacheFiles[i].FileName);
                  }
              }
          }
     private string GetParentPath(string currentPath)
          {
              string delimiter = "\\\\";
              System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(delimiter);
              string[] childPath = rx.Split(currentPath);
            
     int parentLength = childPath.Length - 1;
              string[] parentPath = new string[parentLength + 1];
             
    int i = 0;
              for (i = 0; i <= parentLength - 1; i++)
              {
                  parentPath[i] = childPath[i];
              }
              if (parentPath.Length == 1)
              {
                  return "\\";
              }
              else
              {
                  return string.Join("\\", parentPath);
              }
          }
         
          public void Clear()
          {
              if (Cache.CacheSize > Cache.MaxSize)
              {
                  int i;
                  for (i = Cache.CacheFiles.Count - 1; i >= 0; i += -1)
                  {
                      //Uit de xml gooien.
                      Cache.DeleteFile(Cache.CacheFiles[i].FileName);
                  }
              }
          }

  • Add in CacheFunctions.cs, in "namespace GMapNET"
       public class Comparer : IComparer<CacheFile>
       {
            public int Compare(CacheFile x, CacheFile y)
            {
                if (x.LastUsedDate < y.LastUsedDate)
                {
                    return 1;
                }
                else
                {
                    return -1;
                }
            }
       }

  • Add in CacheFunctions.cs, in every Get ...., in the "if(file.exists)" piece:
    Cache.Update(dir.ToString().Replace(Cache.RootFolder, ""), new FileInfo(dir.ToString()).Length, DateTime.Now);

  • Add in CacheFunctions.cs, in everything without Get ....,
    Cache.Add(dir.ToString().Replace(Cache.RootFolder, ""), new FileInfo(dir.ToString()).Length, DateTime.Now);

  • Add in CacheFunctions.cs, in public string CacheLocation»SET
    Cache.RootFolder = cache;

That should be exact every adjustment that I made ;-)

-Edit Codeplex quite messed up stuff, but I hope it is readable-

Coordinator
Jun 2, 2009 at 8:17 PM

cool, does speed it ok, can you build some demo to test it? ;}

p.s. you can use html editor here and paste all stuff in '<pre>my code</pre>'

 

Jun 3, 2009 at 11:32 AM

Ah, thanks for the tip. As for the demo, I have the build were it was meant for here somewere.. I will search for it ;-)

Jun 3, 2009 at 5:32 PM

Ok, I have created a demo that *should* work, but where should I upload it?

Coordinator
Jun 3, 2009 at 7:55 PM

http://gmap4dotnet.codeplex.com/SourceControl/UploadPatch.aspx

Jun 3, 2009 at 7:59 PM

Done

Coordinator
Jun 3, 2009 at 8:12 PM

quite old version huh ;}

Jun 3, 2009 at 8:23 PM

That's what I said, I only created the patch for that version, and I don't really feel the need to update it to the latest version. But I hope I can help with this, because the system is the same, just the implementation has to be changed

Coordinator
Jun 3, 2009 at 8:25 PM

yes, you can make your custom cache provider with limits support

Jun 3, 2009 at 8:32 PM

Exactly. Point is, I don't have time the next weeks, I have "testweek" at school, and after that I have "big vacation", so maybe I look at it then.. ;}

Coordinator
Jun 3, 2009 at 8:45 PM

havea a great rest ;}