/[EmuXPortal]/branches/mono/EmuXPortal.Api/Api/RomCache.cs
ViewVC logotype

Contents of /branches/mono/EmuXPortal.Api/Api/RomCache.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 396 - (show annotations) (download)
Sun Jun 23 23:32:26 2019 UTC (6 months, 3 weeks ago) by william
File size: 14918 byte(s)
use HashSet instead of List
1 using System;
2 using System.IO;
3 using Enterprise.Logging;
4 using System.Security.Cryptography;
5 using System.Text;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.Windows.Forms;
9 using System.Linq;
10
11 namespace EmuXPortal.Api
12 {
13 public interface IPlatformCache {
14
15 bool isPlatformPathCached (string platform_path);
16 IEmuPlatform GetCachedPlatform(string platform_path);
17 IEmuConfig GetCachedPlatformAsEmuConfig(string platform_path);
18
19 HashSet<IEmuPlatform> GetCachedPlatforms();
20 HashSet<IEmuConfig> GetCachedPlatformsAsEmuConfigs();
21
22 IRomConfig GetCachedRom(string platform_path, string rom_file);
23
24 }
25 public class PlatformCache : IPlatformCache
26 {
27 public static IPlatformCache Create (AbortEvent abort_event)
28 {
29 return new PlatformCache(abort_event);
30 }
31 public static IPlatformCache Create (string cache_path, AbortEvent abort_event)
32 {
33 return new PlatformCache(cache_path, abort_event);
34 }
35 public static IPlatformCache Create (AbortEvent abort_event,string platform_path, bool bGenerateAllCache)
36 {
37 return new PlatformCache(abort_event,platform_path, bGenerateAllCache);
38 }
39 public static IPlatformCache Create (string cache_path, AbortEvent abort_event,string platform_path, bool bGenerateAllCache)
40 {
41 return new PlatformCache(cache_path, abort_event,platform_path, bGenerateAllCache);
42 }
43 internal PlatformCache (AbortEvent abort_event)
44 {
45 BuildCache(abort_event);
46 }
47 internal PlatformCache (string cache_path, AbortEvent abort_event)
48 {
49 BuildCache(cache_path, abort_event);
50 }
51 internal PlatformCache (AbortEvent abort_event, string platform_path, bool bGenerateAllCache) : this("",abort_event, platform_path, bGenerateAllCache)
52 {
53 }
54 internal PlatformCache (string cache_path, AbortEvent abort_event, string platform_path, bool bGenerateAllCache)
55 {
56 if (bGenerateAllCache) {
57 BuildCache (abort_event);
58 } else {
59 m_CachedPlatforms = new HashSet<IEmuPlatform> ();
60 var cached_platform_paths = RomCache.GetCachedPlatformPaths ();
61 }
62 if (!isPlatformPathCached(platform_path)) {
63 // platform does not exist in cache to add it
64 RomCache cache = new RomCache(abort_event,platform_path);
65 var platform = cache.GetPlatform();
66 m_CachedPlatforms.Add(platform);
67 }
68 }
69 private void BuildCache (AbortEvent abort_event)
70 {
71 BuildCache("", abort_event);
72 }
73 private void BuildCache (string cache_path, AbortEvent abort_event)
74 {
75 m_CachedPlatforms = new HashSet<IEmuPlatform> ();
76 var cached_platform_paths = RomCache.GetCachedPlatformPaths (cache_path);
77
78 if (cached_platform_paths.Count == 0) {
79 // the cache has not been created
80 Config.LoadConfig (this);
81 string rom_path = Config.RomPath;
82 var dirs = Directory.GetDirectories (rom_path, "*.*", SearchOption.TopDirectoryOnly);
83 foreach (var dir in dirs) {
84 RomCache cache = new RomCache (abort_event, dir);
85 var platform = cache.GetPlatform ();
86 if (platform.PlatformParsed) {
87 m_CachedPlatforms.Add (platform);
88 }
89 }
90 } else {
91 foreach (var cached_platform_path in cached_platform_paths) {
92 //gLog.Debug.WriteLine("Cached: {0}", cached_platform_path);
93 RomCache cache = new RomCache (cache_path, abort_event, cached_platform_path);
94 var platform = cache.GetPlatform ();
95 if (platform.PlatformParsed) {
96 m_CachedPlatforms.Add (platform);
97 }
98 }
99 }
100 }
101 public bool isPlatformPathCached (string platform_path)
102 {
103 bool cached = false;
104 foreach (var t in m_CachedPlatforms) {
105 if (t.PlatformPath.ToLower () == platform_path.ToLower ()) {
106 cached = true;
107 break;
108 }
109 }
110 return cached;
111 }
112 private HashSet<IEmuPlatform> m_CachedPlatforms;
113 private HashSet<IEmuPlatform> CachedPlatforms{get { return m_CachedPlatforms;} }
114
115 public HashSet<IEmuPlatform> GetCachedPlatforms() { return this.CachedPlatforms; }
116 public HashSet<IEmuConfig> GetCachedPlatformsAsEmuConfigs ()
117 {
118 HashSet<IEmuConfig> configs = new HashSet<IEmuConfig> ();
119 foreach (var platform in this.CachedPlatforms) {
120 EmuXPortal.Api.EmuConfigLoader.EmuConfig config = new EmuConfigLoader.EmuConfig(platform);
121 configs.Add(config);
122 }
123 return configs;
124 }
125 public IEmuPlatform GetCachedPlatform (string platform_path)
126 {
127 IEmuPlatform config = null;
128 if (isPlatformPathCached (platform_path)) {
129 foreach (var platform in this.CachedPlatforms) {
130 if (platform.PlatformPath.ToLower () == platform_path.ToLower ()) {
131 config = platform;
132 break;
133 }
134 }
135 }
136 return config;
137 }
138 public IEmuConfig GetCachedPlatformAsEmuConfig (string platform_path)
139 {
140 IEmuConfig config = null;
141 if (isPlatformPathCached (platform_path)) {
142 foreach (var platform in this.CachedPlatforms) {
143 if (platform.PlatformPath.ToLower () == platform_path.ToLower ()) {
144 config = new EmuConfigLoader.EmuConfig(platform);
145 break;
146 }
147 }
148 }
149 return config;
150 }
151 public IRomConfig GetCachedRom (string platform_path, string rom_file)
152 {
153 if (!isPlatformPathCached (platform_path)) {
154 gLog.Debug.WriteLine ("Platform is not cached: {0}", platform_path);
155 return null;
156 }
157 var config = GetCachedPlatform (platform_path);
158 if (config.HasExternalConfigs) {
159 gLog.Debug.WriteLine ("Platform '{0}' cannot have roms", platform_path);
160 return null;
161 }
162 // find the rom
163 var roms = config.Roms;
164 IEmuRom ier = null;
165 foreach (var rom in roms) {
166 if (rom.RomFile.ToLower () == rom_file.ToLower ()) {
167 ier = rom;
168 break;
169 }
170 }
171 if (ier == null) {
172 gLog.Debug.WriteLine ("Platform '{0}' could not find cached rom: {1}", platform_path, rom_file);
173 return null;
174 }
175 IEmuConfig iec = new EmuConfigLoader.EmuConfig(ier.PlatformConfig);
176 RomLoader.RomConfig rc = new RomLoader.RomConfig(ier.RomFile,ier.RomImage,iec);
177 return rc;
178 }
179 }
180 public interface IRomCache
181 {
182 bool CacheLoaded {get;}
183 bool LoadCache ();
184 void SaveCache();
185 IEmuPlatform GetPlatform();
186 }
187 internal class RomCache : IRomCache
188 {
189 internal static HashSet<string> GetCachedPlatformPaths ()
190 {
191 return GetCachedPlatformPaths("");
192 }
193 internal static HashSet<string> GetCachedPlatformPaths (string m_cache_path)
194 {
195 HashSet<string> cached_platform_paths = new HashSet<string> ();
196 Dictionary<string, string> _map = new Dictionary<string, string> ();
197 // read cache map
198 string cache_map_file = RomCache.GetCacheMapFile (m_cache_path);
199 FileInfo f_map = new FileInfo (cache_map_file);
200 Serializer<Dictionary<string, string>> serializer = new Serializer<Dictionary<string, string>> ();
201 if (f_map.Exists) {
202 serializer.DeSerialize (f_map.FullName, out _map);
203 } else {
204 return new HashSet<string>();
205 }
206 foreach (var t in _map) {
207 var key = t.Key;
208 var value = t.Value;
209 //gLog.Debug.WriteLine("[key:{0}] [value:{1}]", key, value);
210 cached_platform_paths.Add(t.Value);
211 }
212 cached_platform_paths = new HashSet<string> (cached_platform_paths.OrderBy (s => s));
213 return cached_platform_paths;
214 }
215
216 private const string _CACHE_FOLDER = "emuxportal_cache";
217 private const string _CACHE_FILE_EXTENSTION = "_platformcache.bin";
218 private const string _CACHE_MAP_FILE = "cache.map";
219
220 private Dictionary<string, string> CacheMap = new Dictionary<string, string>();
221 private bool bCacheMapLoaded =false;
222 private string m_platform_path;
223 private IEmuPlatform m_cache;
224
225 private string m_cache_path = "";
226
227 private static string GetCacheMapFile (string path)
228 {
229 string cache_map_file = "";
230 if (path == "") {
231 cache_map_file = Enterprise.CrossPlatform.OSInfo.FormatPath (string.Format (@"{0}\{1}", Application.StartupPath, _CACHE_MAP_FILE));
232 } else {
233 cache_map_file = Enterprise.CrossPlatform.OSInfo.FormatPath (string.Format (@"{0}\{1}", path, _CACHE_MAP_FILE));
234 }
235 return cache_map_file;
236 }
237 private static string GetPlatformCacheFile (string path, string platform_path)
238 {
239 string platform_cache_filename = string.Format ("{0}{1}", CreateCacheFileHash (platform_path), _CACHE_FILE_EXTENSTION);
240 string platform_cache_file = "";
241 if (path == "") {
242 platform_cache_file = Enterprise.CrossPlatform.OSInfo.FormatPath (string.Format (@"{0}\{1}", _CACHE_FOLDER, platform_cache_filename));
243 } else {
244 platform_cache_file = Enterprise.CrossPlatform.OSInfo.FormatPath (string.Format (@"{0}\{1}\{2}", path, _CACHE_FOLDER, platform_cache_filename));
245 }
246 return platform_cache_file;
247 }
248
249 private AbortEvent abort_event = null;
250 public RomCache (AbortEvent abort_event, string platform_path) : this("", abort_event, platform_path)
251 {
252 }
253 public RomCache (string cache_path, AbortEvent abort_event, string platform_path)
254 {
255 this.m_cache_path = cache_path;
256 this.abort_event = abort_event;
257 m_platform_path = platform_path;
258 m_cache = new EmuPlatform ();
259
260 if (!this.LoadCache ()) {
261 GenerateCache ();
262 if (m_cache.PlatformParsed) {
263 SaveCache ();
264 }
265 } else {
266 UpdateCache();
267 SaveCache ();
268 }
269 }
270
271 public IEmuPlatform GetPlatform() {
272 return m_cache;
273 }
274
275 private bool m_CacheLoaded;
276 public bool CacheLoaded { get { return m_CacheLoaded; } private set { m_CacheLoaded = value;}}
277 private void GenerateCache ()
278 {
279 gLog.Warn.WriteLine ("Generating cache for path: '{0}'", m_platform_path);
280 m_cache = new EmuPlatform (abort_event, false, m_platform_path);
281 if (m_cache.PlatformParsed) {
282 AddToCacheMap (RomCache.GetPlatformCacheFile(this.m_cache_path, m_platform_path), m_platform_path);
283 }
284 this.CacheLoaded = m_cache.PlatformParsed;
285
286 }
287 public bool LoadCache ()
288 {
289 string cache_file = RomCache.GetPlatformCacheFile(this.m_cache_path, this.m_platform_path);
290 FileInfo fi = new FileInfo (cache_file);
291 if (!fi.Exists) {
292 this.CacheLoaded = false;
293 return false;
294 }
295 gLog.Info.WriteLine ("Starting deserialization of cache from file...");
296 Serializer<IEmuPlatform> serializer = new Serializer<IEmuPlatform> ();
297 if (!serializer.DeSerialize (cache_file, out m_cache)) {
298 this.CacheLoaded = false;
299 return false;
300 } else {
301 this.CacheLoaded = true;
302 return true;
303 }
304 }
305 public void SaveCache ()
306 {
307 if (!this.CacheLoaded) {
308 return;
309 }
310 gLog.Info.WriteLine("Starting serialization of cache to file...");
311 Serializer<IEmuPlatform> serializer = new Serializer<IEmuPlatform>();
312 string cache_file = RomCache.GetPlatformCacheFile(this.m_cache_path, this.m_platform_path);
313 if (!serializer.Serialize (cache_file, m_cache)) {
314 throw new Exception (string.Format ("Failed to save cache to file: '{0}'", cache_file));
315 }
316 }
317
318 // private void OnCreateCache ()
319 // {
320 // DirectoryInfo di = new DirectoryInfo (m_platform_path);
321 // RomCache.GetPlatformCacheFile(this.m_cache_path, m_platform_path)
322 // gLog.Debug.WriteLine ("CACHE_FILE: {0}",CACHE_FILE);
323 // }
324 private bool LoadCacheMap ()
325 {
326 if (bCacheMapLoaded)
327 return true;
328 string cache_map_file = RomCache.GetCacheMapFile(this.m_cache_path);
329 FileInfo f_map = new FileInfo (cache_map_file);
330 Serializer<Dictionary<string, string>> serializer = new Serializer<Dictionary<string, string>>();
331 if (f_map.Exists) {
332 // load the file
333 serializer.DeSerialize (f_map.FullName, out CacheMap);
334 gLog.Info.WriteLine ("Loaded Cache map file: '{0}'", f_map.FullName);
335 gLog.Debug.WriteLine ("Found {0} cached map entries", CacheMap.Count);
336 bCacheMapLoaded = true;
337 } else {
338 bCacheMapLoaded = false;
339 }
340 return bCacheMapLoaded;
341 }
342 private void AddToCacheMap (string cache_file, string platform_path)
343 {
344 Serializer<Dictionary<string, string>> serializer = new Serializer<Dictionary<string, string>> ();
345 if (!LoadCacheMap ()) {
346 CacheMap = new Dictionary<string, string> ();
347 }
348 if (!CacheMap.ContainsKey (cache_file)) {
349 CacheMap.Add(cache_file,platform_path);
350 }
351 string cache_map_file = RomCache.GetCacheMapFile(this.m_cache_path);
352 serializer.Serialize (cache_map_file, CacheMap);
353 }
354
355 private static string CreateCacheFileHash(string imagepath)
356 {
357 Guid result = new Guid ();
358 using (MD5 md5 = MD5.Create ()){
359 byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(imagepath));
360 result = new Guid(hash);
361 }
362 return result.ToString();
363 }
364 private string CreateCacheFileHash()
365 {
366 return CreateCacheFileHash (m_platform_path);
367 }
368
369
370 private void RemoveMissingRomEntries ()
371 {
372 gLog.Info.WriteLine ("Purging missing rom entries");
373 Stopwatch st = new Stopwatch();
374 st.Start();
375 var roms = new HashSet<IEmuRom>(this.m_cache.Roms);
376 foreach (var t in this.m_cache.Roms) {
377 string romfile = t.RomFile;
378 if (!File.Exists (romfile)) {
379 gLog.Debug.WriteLine(" Purging Missing rom: {0}", romfile);
380 roms.Remove(t);
381 }
382 }
383 this.m_cache.Roms = roms;
384 gLog.Info.WriteLine ("Finished purging missing rom entries");
385 st.Stop();
386 gLog.Profiler.WriteLine("Purge took: {0} seconds", st.Elapsed.TotalSeconds);
387 }
388
389
390 private void UpdateCachedConfig() {
391 // grab only the updated config
392 var updated_cache = new EmuPlatform (abort_event, true, this.m_cache.PlatformPath);
393 // store the current rom list
394 var roms = new HashSet<IEmuRom>(this.m_cache.Roms);
395 // overwrite the cache with the updated cconfig
396 m_cache = updated_cache;
397 // restore the original roms
398 m_cache.Roms = roms;
399 }
400 private bool UpdateRomList ()
401 {
402 HashSet<IEmuRom> roms = new HashSet<IEmuRom> ();
403 HashSet<string> images = EmuRom.GetImagesInPath(m_cache.EmulatorRomPath);
404 bool result = EmuRom.EnumerateRoms (m_cache, images, m_cache.Roms, this.abort_event, m_cache.PlatformPath, m_cache.Extenstions, out roms);
405 images.Clear();
406 images=null;
407 if (result) {
408 m_cache.Roms = roms;
409 }
410 return result;
411 }
412 private void UpdateCache ()
413 {
414 if (!Directory.Exists (this.m_cache.PlatformPath)) {
415 // the platform path does not exist (just retuned the cached data)
416 return;
417 }
418 // update the cached config settings for the platform (which also updates the external configs if present)
419 UpdateCachedConfig ();
420 int index = 0;
421 if (!m_cache.HasExternalConfigs) {
422 // an platform that has external configs cannot have roms
423 RemoveMissingRomEntries ();
424 if (UpdateRomList ()) {
425 // list roms
426 index = 0;
427 foreach (var rom in m_cache.Roms) {
428 if (rom.RomFile.ToLower().Contains ("16 tiles")) {
429 gLog.Debug.WriteLine ("Rom[{0}]: [file:{1}] [image:{2}]", index, rom.RomFile, rom.RomImage);
430 }
431
432 index++;
433 }
434 }
435 } else {
436 if (m_cache.Roms.Count > 0) {
437 gLog.Warn.WriteLine("Platform: '{0}' (a platform with external configs cannot have roms!)", m_cache.PlatformNameLong);
438 }
439 // index = 0;
440 // foreach (var t in m_cache.ExternalConfigs) {
441 // gLog.Debug.WriteLine("Config[{0}]: [file:{1}]",index,t.ConfigFile);
442 // index++;
443 // }
444 }
445 }
446 }
447 }
448
449

  ViewVC Help
Powered by ViewVC 1.1.22