Merge pull request #745 in FS/freeswitch from ~MICHAELGG/freeswitch:fs-8932-mod_managed_embedded_loading to master

* commit 'c96d0098cc283a99adee10606d51b601d5658566':
  FS-8932 - Add in process loading via LoadEmbeddedPlugins
This commit is contained in:
Mike Jerris 2016-03-14 10:55:38 -05:00
commit 471e4453bf
2 changed files with 51 additions and 4 deletions

View File

@ -141,7 +141,9 @@ namespace FreeSWITCH {
static void watcher_Changed(object sender, FileSystemEventArgs e) {
Action<string> queueFile = fileName => {
var currentPi = pluginInfos.FirstOrDefault(p => string.Compare(fileName, p.FileName, StringComparison.OrdinalIgnoreCase) == 0);
var currentPi = pluginInfos
.Where(x => !string.IsNullOrEmpty(x.FileName))
.FirstOrDefault(p => string.Compare(fileName, p.FileName, StringComparison.OrdinalIgnoreCase) == 0);
if (currentPi != null) {
var noReload = currentPi.Manager.ApiExecutors.Any(x => (x.PluginOptions & PluginOptions.NoAutoReload) == PluginOptions.NoAutoReload) ||
currentPi.Manager.AppExecutors.Any(x => (x.PluginOptions & PluginOptions.NoAutoReload) == PluginOptions.NoAutoReload);
@ -259,7 +261,7 @@ namespace FreeSWITCH {
System.Threading.Interlocked.Increment(ref appDomainCount);
setup.ApplicationName = Path.GetFileName(fileName) + "_" + appDomainCount;
var domain = AppDomain.CreateDomain(setup.ApplicationName, null, setup);
PluginManager pm;
try {
pm = (PluginManager)domain.CreateInstanceAndUnwrap(pmType.Assembly.FullName, pmType.FullName, null);
@ -276,9 +278,17 @@ namespace FreeSWITCH {
return;
}
addPlugin(fileName, domain, pm);
}
static void addPlugin(string fileName, AppDomain domain, PluginManager pm) {
// Update dictionaries atomically
lock (loaderLock) {
unloadFile(fileName);
if (!string.IsNullOrEmpty(fileName)) {
if (domain == null) throw new ApplicationException("File based plugins must specify an AppDomain.");
unloadFile(fileName);
}
if (domain == null) domain = AppDomain.CurrentDomain;
var pi = new PluginInfo { FileName = fileName, Domain = domain, Manager = pm };
pluginInfos.Add(pi);
@ -298,6 +308,11 @@ namespace FreeSWITCH {
}
}
public static void LoadEmbeddedPlugins(Assembly asm) {
var pm = new EmbeddedPluginManager(asm);
addPlugin(null, null, pm);
}
static void unloadFile(string fileName) {
List<PluginInfo> pisToRemove;
lock (loaderLock) {

View File

@ -250,7 +250,7 @@ namespace FreeSWITCH {
}
}
public void BlockUntilUnloadIsSafe() {
public virtual void BlockUntilUnloadIsSafe() {
if (isUnloading) throw new InvalidOperationException("PluginManager is already unloading.");
isUnloading = true;
unloadCount = ApiExecutors.Count + AppExecutors.Count;
@ -310,4 +310,36 @@ namespace FreeSWITCH {
}
internal class EmbeddedPluginManager : PluginManager {
// This is for cases where FreeSWITCH is "embedded", that is a .NET app hosts the FS core lib itself.
// In such a case, there may be plugins defined in the main process that need to share address space
// and be loaded from the main assembly. This class plus changes in Loader.cs (null filenames=embedded)
// work together to allow such plugins to work. These plugins cannot be reloaded.
Assembly asm;
public EmbeddedPluginManager(Assembly asm) {
this.asm = asm;
var allTypes = asm.GetExportedTypes();
var opts = GetOptions(allTypes);
AddApiPlugins(allTypes, opts);
AddAppPlugins(allTypes, opts);
}
protected override bool LoadInternal(string fileName) {
throw new NotImplementedException("EmbeddedPluginManager should not have Load[Internal] called.");
}
public override void BlockUntilUnloadIsSafe() {
throw new NotImplementedException("EmbeddedPluginManager should never be unloaded.");
}
}
public static class EmbeddedLoader {
public static void LoadEmbeddedPlugins(Assembly asm) {
Loader.LoadEmbeddedPlugins(asm);
}
}
}