Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/PluginCache.cs @ 5105

Last change on this file since 5105 was 5105, checked in by ascheibe, 13 years ago

ported most of the slave code to 3.4 #1233

File size: 8.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.IO;
25using System.Linq;
26using System.Runtime.CompilerServices;
27using HeuristicLab.Services.Hive.Common.ServiceContracts;
28using HeuristicLab.Services.Hive.Common.DataTransfer;
29using HeuristicLab.PluginInfrastructure;
30using HeuristicLab.PluginInfrastructure.Manager;
31using System.Threading;
32using System.Reflection;
33using HeuristicLab.Clients.Hive.Salve;
34
35namespace HeuristicLab.Clients.Hive.Slave {
36  public class PluginCache {
37    private static object locker = new object();
38    public const string ConfigFileName = "Sandbox.config";
39
40    private static PluginCache instance = null;
41
42    public string PluginCacheDir { get; set; }
43    public string PluginTempBaseDir { get; set; }
44
45    private List<PluginDescription> cachedPlugins = new List<PluginDescription>();
46
47    private PluginManager pm;
48
49    public static PluginCache Instance {
50      get {
51        if (instance == null)
52          instance = new PluginCache();
53        return instance;
54      }
55    }
56
57    public string ConfigFilePath {
58      get {
59        return Path.Combine(PluginCacheDir, ConfigFileName);
60      }
61    }
62
63    public PluginCache() {
64      PluginCacheDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PluginCache");
65      PluginTempBaseDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PluginTemp");
66
67      this.pm = new PluginManager(PluginCacheDir);
68      DoUpdateRun();
69    }
70
71    private void DoUpdateRun() {
72      if (!Directory.Exists(PluginCacheDir)) {
73        Directory.CreateDirectory(PluginCacheDir);
74      }
75      pm.DiscoverAndCheckPlugins();
76      cachedPlugins = new List<PluginDescription>(pm.Plugins);
77    }
78
79    [MethodImpl(MethodImplOptions.Synchronized)]
80    public void CopyPluginsForJob(List<Plugin> requests, Guid jobId) {
81      lock (locker) {
82        String targetDir = Path.Combine(PluginTempBaseDir, jobId.ToString());
83
84        if (Directory.Exists(targetDir)) {
85          Directory.Delete(targetDir, true);
86        }
87
88        DirectoryInfo di = Directory.CreateDirectory(targetDir);
89
90        foreach (Plugin requestedPlugin in requests) {
91          PluginDescription pd = cachedPlugins.Where(cp =>
92            cp.Name == requestedPlugin.Name &&
93            cp.Version.Major == requestedPlugin.Version.Major &&
94            cp.Version.Minor == requestedPlugin.Version.Minor).SingleOrDefault();
95          if (pd != null) {
96            foreach (IPluginFile ipf in pd.Files) {
97              File.Copy(ipf.Name, Path.Combine(targetDir, Path.GetFileName(ipf.Name)));
98            }
99          }
100        }
101
102        // copy config file
103        File.Copy(ConfigFilePath, Path.Combine(targetDir, ConfigFileName));
104
105        // copy files from PluginInfrastructure, which are not declared
106        string baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
107        CopyFile(baseDir, targetDir, "HeuristicLab.PluginInfrastructure-3.3.dll");
108        CopyFile(baseDir, targetDir, "ICSharpCode.SharpZipLib.dll");
109        CopyFile(baseDir, targetDir, "ICSharpCode.SharpZipLib License.txt");
110
111        // copy slave plugins, otherwise its not possible to register the UnhandledException handler to the appdomain
112        CopyFile(baseDir, targetDir, "HeuristicLab.Clients.Hive.Slave-3.4.dll");
113        CopyFile(baseDir, targetDir, "HeuristicLab.Clients.Hive-3.4.dll");
114        CopyFile(baseDir, targetDir, "HeuristicLab.Services.Hive.Common-3.4.dll");
115        CopyFile(baseDir, targetDir, "HeuristicLab.Hive-3.4.dll");
116
117        //TODO: remove, just needed for unit tests
118        CopyFile(baseDir, targetDir, "HeuristicLab.Clients.Hive.Slave.Tests-3.4.dll");
119      }
120    }
121
122    private void CopyFile(string baseDir, string targetDir, string fileName) {
123      if (!File.Exists(Path.Combine(targetDir, fileName))) File.Copy(Path.Combine(baseDir, fileName), Path.Combine(targetDir, fileName));
124    }
125
126    [MethodImpl(MethodImplOptions.Synchronized)]
127    internal void PreparePlugins(Job myJob, JobData jobData) {
128      lock (locker) {
129        Logger.Debug("Fetching plugins for job");
130
131        IEnumerable<Plugin> pluginDescriptions = WcfService.Instance.GetPlugins();
132        List<Plugin> requiredPlugins = new List<Plugin>();
133        foreach (Guid pluginId in myJob.PluginsNeededIds) {
134          Plugin pl = pluginDescriptions.FirstOrDefault(p => p.Id == pluginId);
135          if (pl != null)
136            requiredPlugins.Add(pl);
137        }
138
139        List<Plugin> localPlugins = new List<Plugin>();
140        List<Plugin> missingPlugins = new List<Plugin>();
141        List<Guid> missingGuids = new List<Guid>();
142        bool found = false;
143
144        foreach (Plugin info in requiredPlugins) {
145          //we MAY run in problems here - if there is a plugin twice in requests, there may be added two different versions of the plugin
146          foreach (PluginDescription cachedPlugin in cachedPlugins) {
147            if (info.Name == cachedPlugin.Name && info.Version == cachedPlugin.Version) {
148              localPlugins.Add(new Plugin() { Id = new Guid(), Name = info.Name, Version = info.Version });
149              found = true;
150
151              break;
152            }
153          }
154          if (!found) {
155            Logger.Debug("Plugin NOT found " + info.Name + ", " + info.Version);
156            missingPlugins.Add(info);
157            missingGuids.Add(info.Id);
158          }
159          found = false;
160        }
161
162        Logger.Debug("First run - Update the plugins in the cache");
163        localPlugins.AddRange(missingPlugins);
164
165        IEnumerable<PluginData> updateablePlugins = WcfService.Instance.GetPluginDatas(missingGuids);
166
167        foreach (PluginData updateablePlugin in updateablePlugins) {
168          Plugin pluginDescription = pluginDescriptions.Where(desc => desc.Id == updateablePlugin.PluginId).SingleOrDefault();
169          if (pluginDescription != null) {
170
171            PluginDescription pd = cachedPlugins.Where(cachedPlugin =>
172                cachedPlugin.Name == pluginDescription.Name &&
173                cachedPlugin.Version.Major == pluginDescription.Version.Major &&
174                cachedPlugin.Version.Minor == pluginDescription.Version.Major).SingleOrDefault();
175
176            if (pd != null) {
177              foreach (IPluginFile ipf in pd.Files) {
178                Logger.Debug(string.Format("deleting {0}", Path.GetFileName(ipf.Name)));
179                File.Delete(ipf.Name);
180              }
181            }
182            File.WriteAllBytes(Path.Combine(PluginCacheDir, Path.GetFileName(pluginDescription.Name)), updateablePlugin.Data);
183          }
184          //TODO: error handling on pluginDescription, should be found
185        }
186
187        PluginData configFile = WcfService.Instance.GetConfigurationFile();
188        File.WriteAllBytes(ConfigFilePath, configFile.Data);
189
190        DoUpdateRun();
191        CopyPluginsForJob(requiredPlugins, myJob.Id);
192      }
193    }
194
195    internal void DeletePluginsForJob(Guid id) {
196      try {
197        Logger.Debug("unloading...");
198        int tries = 5;
199        while (tries > 0) {
200          try {
201            Directory.Delete(Path.Combine(PluginTempBaseDir, id.ToString()), true);
202            tries = 0;
203          }
204          catch {
205            Thread.Sleep(1000);
206            tries--;
207            if (tries == 0) throw;
208          }
209        }
210      }
211      catch (Exception ex) {
212        Logger.Debug("failed while unloading " + id + " with exception " + ex);
213      }
214    }
215
216
217  }
218}
Note: See TracBrowser for help on using the repository browser.