using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using SuperSocket.Common;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Logging;
using SuperSocket.SocketBase.Provider;
using SuperSocket.SocketEngine.Configuration;
using SuperSocket.SocketBase.Metadata;
namespace SuperSocket.SocketEngine
{
class AppDomainWorkItemFactoryInfoLoader : WorkItemFactoryInfoLoader
{
public AppDomainWorkItemFactoryInfoLoader(IConfigurationSource config, ILogFactory passedInLogFactory)
: base(config, passedInLogFactory)
{
InitliazeValidationAppDomain();
}
public AppDomainWorkItemFactoryInfoLoader(IConfigurationSource config)
: base(config)
{
InitliazeValidationAppDomain();
}
private AppDomain m_ValidationAppDomain;
private TypeValidator m_Validator;
private void InitliazeValidationAppDomain()
{
m_ValidationAppDomain = AppDomain.CreateDomain("ValidationDomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.BaseDirectory, string.Empty, false);
var validatorType = typeof(TypeValidator);
m_Validator = (TypeValidator)m_ValidationAppDomain.CreateInstanceAndUnwrap(validatorType.Assembly.FullName, validatorType.FullName);
}
protected override string ValidateProviderType(string typeName)
{
if (!m_Validator.ValidateTypeName(typeName))
throw new Exception(string.Format("Failed to load type {0}!", typeName));
return typeName;
}
protected override ServerTypeMetadata GetServerTypeMetadata(string typeName)
{
return m_Validator.GetServerTypeMetadata(typeName);
}
public override void Dispose()
{
if (m_ValidationAppDomain != null)
{
AppDomain.Unload(m_ValidationAppDomain);
m_ValidationAppDomain = null;
}
base.Dispose();
}
}
class DefaultBootstrapAppDomainWrap : DefaultBootstrap
{
private IBootstrap m_Bootstrap;
public DefaultBootstrapAppDomainWrap(IBootstrap bootstrap, IConfigurationSource config, string startupConfigFile)
: base(config, startupConfigFile)
{
m_Bootstrap = bootstrap;
}
protected override IWorkItem CreateWorkItemInstance(string serviceTypeName, StatusInfoAttribute[] serverStatusMetadata)
{
return new AppDomainAppServer(serviceTypeName, serverStatusMetadata);
}
internal override bool SetupWorkItemInstance(IWorkItem workItem, WorkItemFactoryInfo factoryInfo)
{
return workItem.Setup(m_Bootstrap, factoryInfo.Config, factoryInfo.ProviderFactories.ToArray());
}
internal override WorkItemFactoryInfoLoader GetWorkItemFactoryInfoLoader(IConfigurationSource config, ILogFactory logFactory)
{
return new AppDomainWorkItemFactoryInfoLoader(config, logFactory);
}
}
///
/// AppDomainBootstrap
///
partial class AppDomainBootstrap : MarshalByRefObject, ILoggerProvider, IBootstrap, IDisposable
{
private IBootstrap m_InnerBootstrap;
///
/// Gets all the app servers running in this bootstrap
///
public IEnumerable AppServers
{
get { return m_InnerBootstrap.AppServers; }
}
///
/// Gets the config.
///
public IRootConfig Config
{
get { return m_InnerBootstrap.Config; }
}
///
/// Gets the bootstrap logger.
///
ILog ILoggerProvider.Logger
{
get
{
var loggerProvider = m_InnerBootstrap as ILoggerProvider;
if (loggerProvider == null)
return null;
return loggerProvider.Logger;
}
}
///
/// Gets the startup config file.
///
public string StartupConfigFile
{
get { return m_InnerBootstrap.StartupConfigFile; }
}
///
/// Initializes a new instance of the class.
///
public AppDomainBootstrap(IConfigurationSource config)
{
string startupConfigFile = string.Empty;
if (config == null)
throw new ArgumentNullException("config");
var configSectionSource = config as ConfigurationSection;
if (configSectionSource != null)
startupConfigFile = configSectionSource.GetConfigSource();
//Keep serializable version of configuration
if(!config.GetType().IsSerializable)
config = new ConfigurationSource(config);
//Still use raw configuration type to bootstrap
m_InnerBootstrap = CreateBootstrapWrap(this, config, startupConfigFile);
AppDomain.CurrentDomain.SetData("Bootstrap", this);
}
protected virtual IBootstrap CreateBootstrapWrap(IBootstrap bootstrap, IConfigurationSource config, string startupConfigFile)
{
return new DefaultBootstrapAppDomainWrap(this, config, startupConfigFile);
}
///
/// Initializes the bootstrap with the configuration
///
///
public bool Initialize()
{
return m_InnerBootstrap.Initialize();
}
///
/// Initializes the bootstrap with the configuration and config resolver.
///
/// The server config resolver.
///
public bool Initialize(Func serverConfigResolver)
{
return m_InnerBootstrap.Initialize(serverConfigResolver);
}
///
/// Initializes the bootstrap with the configuration and config resolver.
///
/// The log factory.
///
public bool Initialize(ILogFactory logFactory)
{
return m_InnerBootstrap.Initialize(logFactory);
}
///
/// Initializes the bootstrap with a listen endpoint replacement dictionary
///
/// The listen end point replacement.
///
public bool Initialize(IDictionary listenEndPointReplacement)
{
return m_InnerBootstrap.Initialize(listenEndPointReplacement);
}
///
/// Initializes the bootstrap with the configuration
///
/// The server config resolver.
/// The log factory.
///
public bool Initialize(Func serverConfigResolver, ILogFactory logFactory)
{
if (logFactory != null)
throw new Exception("You cannot pass in logFactory, if your isolation level is AppDomain!");
return m_InnerBootstrap.Initialize(serverConfigResolver, logFactory);
}
///
/// Starts this bootstrap.
///
///
public StartResult Start()
{
return m_InnerBootstrap.Start();
}
///
/// Stops this bootstrap.
///
public void Stop()
{
m_InnerBootstrap.Stop();
}
public string BaseDirectory
{
get { return m_InnerBootstrap.BaseDirectory; }
}
void IDisposable.Dispose()
{
var disposableBootstrap = m_InnerBootstrap as IDisposable;
if (disposableBootstrap != null)
disposableBootstrap.Dispose();
}
}
}