├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.CN.md ├── README.md ├── examples ├── ExternalAppConfig │ └── NRack.Server.exe.config ├── IsolationConfig │ └── NRack.Server.exe.config └── TestApp │ ├── TestApp.sln │ └── TestApp │ ├── NRack.Examples.TestApp.csproj │ ├── Properties │ └── AssemblyInfo.cs │ ├── TestAppServer.cs │ └── packages.config ├── global.json └── src ├── Build.bat ├── CreateNuGetPackage.bat ├── GlobalAssemblyInfo.cs ├── NRack-Net45.sln ├── NRack.Base ├── AppServer.ConfigHotUpdate.cs ├── AppServer.cs ├── CompositeTargtes │ ├── CompositeTargetBase.cs │ ├── LoggerFactoryCompositeTarget.cs │ ├── MultipleResultCompositeTarget.cs │ └── SingleResultCompositeTarget.cs ├── Config │ ├── ConfigurationElementBase.cs │ ├── GenericConfigurationElementCollectionBase.cs │ ├── HotUpdateAttribute.cs │ ├── IConfigSource.cs │ ├── IServerConfig.cs │ ├── NRackConfig.cs │ └── ServerConfig.cs ├── Configuration │ ├── ConfigurationExtension.cs │ ├── NRackConfigSection.cs │ └── ServerConfigElement.cs ├── DotNetCore │ ├── CompositionContainer.cs │ ├── ExportProvider.cs │ ├── FakeAttributes.cs │ └── LoggingExtensions.cs ├── ErrorEventArgs.cs ├── Extensions.cs ├── IAppEndPoint.cs ├── IAppServer.cs ├── IBootstrap.cs ├── ICompositeTarget.cs ├── IManagedApp.cs ├── IMessageBus.cs ├── IStatusCollector.cs ├── IsolationMode.cs ├── Metadata │ ├── AppServerMetadata.cs │ ├── AppServerMetadataAttribute.cs │ ├── IAppServerMetadata.cs │ ├── StatusInfoAttribute.cs │ └── StatusInfoKeys.cs ├── NRack.Base.Net45.csproj ├── NRack.Base.NetCore.csproj ├── NRack.Base.csproj ├── NRack.Base.csproj.nuspec ├── NRackEnv.cs ├── Properties │ └── AssemblyInfo.cs ├── Provider │ ├── IProviderMetadata.cs │ └── ProviderMetadataAttribute.cs ├── ServerState.cs ├── StartupType.cs ├── StatusInfoCollection.cs ├── packages.NRack.Base.Net45.config └── packages.NRack.Base.config ├── NRack.Server ├── App.config ├── BootstrapBase.cs ├── BootstrapFactory.cs ├── Config │ ├── log4net.config │ └── nlog.config ├── ConfigurationWatcher.cs ├── ControlCommand.cs ├── DefaultBootstrap.cs ├── DefaultStatusCollector.cs ├── IRemoteManagedApp.cs ├── Isolation │ ├── AppAssemblyUpdateState.cs │ ├── AppDomainIsolation │ │ ├── AppDomainApp.cs │ │ └── AppDomainBootstrap.cs │ ├── AssemblyImport.cs │ ├── IsolationApp.cs │ ├── IsolationBootstrap.cs │ ├── MarshalManagedApp.cs │ └── ProcessIsolation │ │ ├── ExternalProcessApp.cs │ │ ├── ExternalProcessAppServerMetadata.cs │ │ ├── ProcessApp.cs │ │ ├── ProcessBootstrap.cs │ │ └── ProcessLocker.cs ├── MefExtensions.cs ├── NRack.Server.Net45.csproj ├── NRack.Server.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Recycle │ ├── AssemblyUpdatedRecycleTrigger.cs │ ├── IRecycleTrigger.cs │ ├── MemoryRecycleTrigger.cs │ └── RecycleTriggerConfig.cs ├── RemoteAppGroup.cs ├── RemoteAppTypeValidator.cs ├── RemoteBootstrapProxy.cs ├── Service │ ├── NRackService.Designer.cs │ ├── NRackService.cs │ ├── NRackServiceInstaller.Designer.cs │ ├── NRackServiceInstaller.cs │ └── SelfInstaller.cs ├── Utils │ ├── PerformanceCounterInfo.cs │ └── ProcessPerformanceCounter.cs ├── nrack.cmd ├── nrack.sh ├── packages.NRack.Server.Net45.config └── packages.NRack.Server.config ├── NRack.Test ├── AppDomainIsolationTest.cs ├── Asserts │ └── Config │ │ ├── AppDomainIsolation.config │ │ ├── Basic.config │ │ └── ProcessIsolation.config ├── NRack.Test.Net45.csproj ├── NRack.Test.csproj ├── ProcessIsolationTest.cs ├── Test.cs ├── TestAppServer.cs ├── packages.NRack.Test.Net45.config └── packages.NRack.Test.config ├── NRack.Worker ├── ManagedAppWorker.cs ├── NRack.Worker.Net45.csproj ├── NRack.Worker.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── packages.NRack.Worker.Net45.config └── packages.NRack.Worker.config ├── NRack.build ├── NRack.nuspec └── NRack.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | 19 | # MSTest test Results 20 | [Tt]est[Rr]esult*/ 21 | [Bb]uild[Ll]og.* 22 | 23 | #NUNIT 24 | *.VisualState.xml 25 | TestResult.xml 26 | 27 | # Build Results of an ATL Project 28 | [Dd]ebugPS/ 29 | [Rr]eleasePS/ 30 | dlldata.c 31 | 32 | *_i.c 33 | *_p.c 34 | *_i.h 35 | *.ilk 36 | *.meta 37 | *.obj 38 | *.pch 39 | *.pdb 40 | *.pgc 41 | *.pgd 42 | *.rsp 43 | *.sbr 44 | *.tlb 45 | *.tli 46 | *.tlh 47 | *.tmp 48 | *.tmp_proj 49 | *.log 50 | *.vspscc 51 | *.vssscc 52 | .builds 53 | *.pidb 54 | *.svclog 55 | *.scc 56 | 57 | # Chutzpah Test files 58 | _Chutzpah* 59 | 60 | # Visual C++ cache files 61 | ipch/ 62 | *.aps 63 | *.ncb 64 | *.opensdf 65 | *.sdf 66 | *.cachefile 67 | 68 | # Visual Studio profiler 69 | *.psess 70 | *.vsp 71 | *.vspx 72 | 73 | # TFS 2012 Local Workspace 74 | $tf/ 75 | 76 | # Guidance Automation Toolkit 77 | *.gpState 78 | 79 | # ReSharper is a .NET coding add-in 80 | _ReSharper*/ 81 | *.[Rr]e[Ss]harper 82 | *.DotSettings.user 83 | 84 | # JustCode is a .NET coding addin-in 85 | .JustCode 86 | 87 | # TeamCity is a build add-in 88 | _TeamCity* 89 | 90 | # DotCover is a Code Coverage Tool 91 | *.dotCover 92 | 93 | # NCrunch 94 | *.ncrunch* 95 | _NCrunch_* 96 | .*crunch*.local.xml 97 | 98 | # MightyMoose 99 | *.mm.* 100 | AutoTest.Net/ 101 | 102 | # Web workbench (sass) 103 | .sass-cache/ 104 | 105 | # Installshield output folder 106 | [Ee]xpress/ 107 | 108 | # DocProject is a documentation generator add-in 109 | DocProject/buildhelp/ 110 | DocProject/Help/*.HxT 111 | DocProject/Help/*.HxC 112 | DocProject/Help/*.hhc 113 | DocProject/Help/*.hhk 114 | DocProject/Help/*.hhp 115 | DocProject/Help/Html2 116 | DocProject/Help/html 117 | 118 | # Click-Once directory 119 | publish/ 120 | 121 | # Publish Web Output 122 | *.[Pp]ublish.xml 123 | *.azurePubxml 124 | 125 | # NuGet Packages Directory 126 | packages/ 127 | ## TODO: If the tool you use requires repositories.config uncomment the next line 128 | #!packages/repositories.config 129 | 130 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 131 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) 132 | !packages/build/ 133 | 134 | # Windows Azure Build Output 135 | csx/ 136 | *.build.csdef 137 | 138 | # Windows Store app package directory 139 | AppPackages/ 140 | 141 | # Others 142 | sql/ 143 | *.Cache 144 | ClientBin/ 145 | [Ss]tyle[Cc]op.* 146 | ~$* 147 | *~ 148 | *.dbmdl 149 | *.dbproj.schemaview 150 | *.pfx 151 | *.publishsettings 152 | node_modules/ 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | *.mdf 166 | *.ldf 167 | 168 | # Business Intelligence projects 169 | *.rdl.data 170 | *.bim.layout 171 | *.bim_*.settings 172 | 173 | # Microsoft Fakes 174 | FakesAssemblies/ 175 | 176 | # dotnet core 177 | *.lock.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | script: 3 | - nuget restore src/NRack.sln 4 | - xbuild src/NRack.sln 5 | - nuget restore src/NRack-Net45.sln 6 | - xbuild src/NRack-Net45.sln 7 | -------------------------------------------------------------------------------- /README.CN.md: -------------------------------------------------------------------------------- 1 | NRack [![Build Status](https://travis-ci.org/kerryjiang/NRack.svg?branch=master)](https://travis-ci.org/kerryjiang/NRack) [![NuGet Version](https://img.shields.io/nuget/v/NRack.svg?style=flat)](https://www.nuget.org/packages/NRack/) 2 | ===== 3 | 4 | **NRack** 是一个服务器应用容器, 他能用宿主和管理你的多个后端服务。 5 | 6 | **功能特点**: 7 | 8 | * **自动化服务宿主**: 宿主你的多个后端程序,无需为每个程序创建服务; 9 | * **外部程序宿主**: 宿主外部的可执行程序,可支持任何可执行程序,无论它是否是.NET开发; 10 | * **多应用隔离**: 支持多个程序的应用程序域级别的隔离或者进程级别的隔离; 11 | * **守护进程** : 程序意外关闭后自动启动; 12 | * **自动化回收管理**: 达到一定条件后自动重启程序; 13 | * **应用程序花园(TODO)**: 为同一应用运行多个实例; 14 | * **计划任务(TODO)**: 定时按计划运行制定程序。 15 | 16 | 文档: [http://nrack.getdocs.net/](http://nrack.getdocs.net/) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NRack [![Build Status](https://travis-ci.org/kerryjiang/NRack.svg?branch=master)](https://travis-ci.org/kerryjiang/NRack) [![NuGet Version](https://img.shields.io/nuget/v/NRack.svg?style=flat)](https://www.nuget.org/packages/NRack/) 2 | ===== 3 | 4 | **NRack** is a server application container, which can be used for your back end services' hosting and management. 5 | 6 | **Features**: 7 | 8 | * **Automatic service hosting**: host your many backend applications, needn't create service for each application; 9 | * **External application hosting**: host external executable application, no matter whether it is developed using .NET; 10 | * **Multiple application isolation**: support isolate your multiple applications using AppDomain and process; 11 | * **Watch dog**: start application after it stops unexpected; 12 | * **Automatic recycle management**: restart application automatically after it satisify some conditions; 13 | * **App Garden(TODO)**: run one application in multiple instances; 14 | * **Task Scheduler(TODO)**: run the designate application on schedule. 15 | 16 | Documentation: [http://nrack.getdocs.net/](http://nrack.getdocs.net/) 17 | -------------------------------------------------------------------------------- /examples/ExternalAppConfig/NRack.Server.exe.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/IsolationConfig/NRack.Server.exe.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/TestApp/TestApp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Examples.TestApp", "TestApp\NRack.Examples.TestApp.csproj", "{E23EDFA0-19AD-44EF-A35B-985F1D0A407D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {E23EDFA0-19AD-44EF-A35B-985F1D0A407D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {E23EDFA0-19AD-44EF-A35B-985F1D0A407D}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {E23EDFA0-19AD-44EF-A35B-985F1D0A407D}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {E23EDFA0-19AD-44EF-A35B-985F1D0A407D}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /examples/TestApp/TestApp/NRack.Examples.TestApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E23EDFA0-19AD-44EF-A35B-985F1D0A407D} 8 | Library 9 | Properties 10 | NRack.Examples.TestApp 11 | NRack.Examples.TestApp 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\AnyLog.0.1.8\lib\net40\AnyLog.dll 35 | True 36 | 37 | 38 | ..\packages\NRack.0.1.1.5\lib\net40\NRack.Base.dll 39 | True 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /examples/TestApp/TestApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestApp")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e23edfa0-19ad-44ef-a35b-985f1d0a407d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /examples/TestApp/TestApp/TestAppServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NRack.Base; 6 | using NRack.Base.Metadata; 7 | 8 | namespace NRack.Examples.TestApp 9 | { 10 | [AppServerMetadata("TestAppServer")] 11 | public class TestAppServer : AppServer 12 | { 13 | public override bool Start() 14 | { 15 | Console.WriteLine("This AppServer is started"); 16 | return true; 17 | } 18 | 19 | public override void Stop() 20 | { 21 | 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/TestApp/TestApp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ 3 | "src" 4 | ], 5 | "sdk": { 6 | "version": "1.0.0-rc2-*" 7 | } 8 | } -------------------------------------------------------------------------------- /src/Build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set fdir=%ProgramFiles(x86)%\MSBuild\14.0 4 | set msbuild="%fdir%\bin\msbuild.exe" 5 | 6 | 7 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S obj') DO RMDIR /S /Q "%%G" 8 | %msbuild% NDock.sln /p:Configuration=Release /t:Clean;Rebuild /p:OutputPath=..\bin\Net40 9 | 10 | reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SKUs\.NETFramework,Version=v4.5" 2>nul 11 | if errorlevel 0 ( 12 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S obj') DO RMDIR /S /Q "%%G" 13 | %msbuild% NDock-Net45.sln /p:Configuration=Release /t:Clean;Rebuild /p:OutputPath=..\bin\Net45 14 | ) 15 | 16 | pause -------------------------------------------------------------------------------- /src/CreateNuGetPackage.bat: -------------------------------------------------------------------------------- 1 | set msbuild="%ProgramFiles(x86)%\MSBuild\14.0\Bin\msbuild.exe" 2 | 3 | 4 | %msbuild% NRack.build /t:BuildAndPack 5 | 6 | pause -------------------------------------------------------------------------------- /src/GlobalAssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyCompany("NRack")] 6 | [assembly: AssemblyProduct("NRack")] 7 | [assembly: AssemblyCopyright("Copyright © 2016")] 8 | [assembly: AssemblyTrademark("")] 9 | [assembly: AssemblyCulture("")] 10 | [assembly: AssemblyVersion("0.1.1.5")] 11 | [assembly: AssemblyFileVersion("0.1.1.5")] 12 | -------------------------------------------------------------------------------- /src/NRack-Net45.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Base.Net45", "NRack.Base\NRack.Base.Net45.csproj", "{406671C6-5DCB-4B23-BD28-FB02C235EAE4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Server.Net45", "NRack.Server\NRack.Server.Net45.csproj", "{7800B7EA-FB3A-4305-9EE7-74A7B5744C45}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{6E0C838A-35D5-4D95-B3F0-6D0560F9C2FD}" 11 | ProjectSection(SolutionItems) = preProject 12 | GlobalAssemblyInfo.cs = GlobalAssemblyInfo.cs 13 | EndProjectSection 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Test.Net45", "NRack.Test\NRack.Test.Net45.csproj", "{B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Worker.Net45", "NRack.Worker\NRack.Worker.Net45.csproj", "{93A2E31D-9AF3-4C9E-986C-1659309F5436}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Release|Any CPU.Build.0 = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(SolutionProperties) = preSolution 42 | HideSolutionNode = FALSE 43 | EndGlobalSection 44 | EndGlobal 45 | -------------------------------------------------------------------------------- /src/NRack.Base/AppServer.ConfigHotUpdate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | #if !DOTNETCORE 5 | using System.Configuration; 6 | using NRack.Base.Configuration; 7 | #else 8 | using Microsoft.Extensions.Logging; 9 | using System.Reflection; 10 | #endif 11 | using System.Linq; 12 | using NRack.Base.Config; 13 | 14 | 15 | namespace NRack.Base 16 | { 17 | interface IConfigValueChangeNotifier 18 | { 19 | bool Notify(string newValue); 20 | } 21 | 22 | class ConfigValueChangeNotifier : IConfigValueChangeNotifier 23 | { 24 | Func m_Handler; 25 | 26 | public ConfigValueChangeNotifier(Func handler) 27 | { 28 | m_Handler = handler; 29 | } 30 | 31 | public bool Notify(string newValue) 32 | { 33 | return m_Handler(newValue); 34 | } 35 | } 36 | 37 | #if !DOTNETCORE 38 | class ConfigValueChangeNotifier : IConfigValueChangeNotifier 39 | where TConfigOption : ConfigurationElement, new() 40 | { 41 | Func m_Handler; 42 | 43 | public ConfigValueChangeNotifier(Func handler) 44 | { 45 | m_Handler = handler; 46 | } 47 | public bool Notify(string newValue) 48 | { 49 | if (string.IsNullOrEmpty(newValue)) 50 | return m_Handler(default(TConfigOption)); 51 | else 52 | return m_Handler(ConfigurationExtension.DeserializeChildConfig(newValue)); 53 | } 54 | } 55 | #endif 56 | public abstract partial class AppServer 57 | { 58 | private Dictionary m_ConfigUpdatedNotifiers = new Dictionary(StringComparer.OrdinalIgnoreCase); 59 | 60 | #if !DOTNETCORE 61 | /// 62 | /// Registers the configuration option value handler, it is used for reading configuration value and reload it after the configuration is changed; 63 | /// 64 | /// The type of the configuration option. 65 | /// The server configuration. 66 | /// The changed config option's name. 67 | /// The handler. 68 | protected bool RegisterConfigHandler(IServerConfig config, string name, Func handler) 69 | where TConfigOption : ConfigurationElement, new() 70 | { 71 | var notifier = new ConfigValueChangeNotifier(handler); 72 | m_ConfigUpdatedNotifiers.Add(name, notifier); 73 | return notifier.Notify(config.Options.GetValue(name)); 74 | } 75 | #endif 76 | 77 | /// 78 | /// Registers the configuration option value handler, it is used for reading configuration value and reload it after the configuration is changed; 79 | /// 80 | /// The server configuration. 81 | /// The changed config option name. 82 | /// The handler. 83 | protected bool RegisterConfigHandler(IServerConfig config, string name, Func handler) 84 | { 85 | var notifier = new ConfigValueChangeNotifier(handler); 86 | m_ConfigUpdatedNotifiers.Add(name, notifier); 87 | return notifier.Notify(config.OptionElements.GetValue(name)); 88 | } 89 | 90 | int CheckConfigOptionsChange(NameValueCollection oldOptions, NameValueCollection newOptions) 91 | { 92 | var changed = 0; 93 | 94 | if (oldOptions == null && newOptions == null) 95 | return changed; 96 | 97 | var oldOptionsDict = oldOptions == null 98 | ? new Dictionary(StringComparer.OrdinalIgnoreCase) 99 | : Enumerable.Range(0, oldOptions.Count) 100 | .Select(i => new KeyValuePair(oldOptions.GetKey(i), oldOptions.Get(i))) 101 | .ToDictionary(p => p.Key, p => p.Value, StringComparer.OrdinalIgnoreCase); 102 | 103 | foreach(var key in newOptions.AllKeys) 104 | { 105 | var newValue = newOptions[key]; 106 | 107 | var oldValue = string.Empty; 108 | 109 | if (oldOptionsDict.TryGetValue(key, out oldValue)) 110 | oldOptionsDict.Remove(key); 111 | 112 | if (string.Compare(newValue, oldValue) == 0) 113 | continue; 114 | 115 | NotifyConfigUpdated(key, newValue); 116 | changed++; 117 | } 118 | 119 | if (oldOptionsDict.Count > 0) 120 | { 121 | foreach (var p in oldOptionsDict) 122 | { 123 | NotifyConfigUpdated(p.Key, string.Empty); 124 | changed++; 125 | } 126 | } 127 | 128 | return changed; 129 | } 130 | 131 | private void NotifyConfigUpdated(string key, string newValue) 132 | { 133 | IConfigValueChangeNotifier notifier; 134 | 135 | if (!m_ConfigUpdatedNotifiers.TryGetValue(key, out notifier)) 136 | return; 137 | 138 | try 139 | { 140 | if (!notifier.Notify(newValue)) 141 | throw new Exception("returned false in the handling logic"); 142 | } 143 | catch (Exception e) 144 | { 145 | Logger.Error("Failed to handle custom configuration reading, name: " + key, e); 146 | } 147 | } 148 | 149 | void IManagedAppBase.ReportPotentialConfigChange(IServerConfig config) 150 | { 151 | var oldConfig = this.Config; 152 | 153 | CheckConfigOptionsChange(oldConfig.Options, config.Options); 154 | CheckConfigOptionsChange(oldConfig.OptionElements, config.OptionElements); 155 | 156 | var updatableConfig = oldConfig as ServerConfig; 157 | 158 | if (updatableConfig == null) 159 | return; 160 | 161 | config.CopyPropertiesTo(p => p.GetCustomAttributes(typeof(HotUpdateAttribute), true).Any(), updatableConfig); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/NRack.Base/CompositeTargtes/CompositeTargetBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Composition.Hosting; 3 | 4 | namespace NRack.Base.CompositeTargets 5 | { 6 | /// 7 | /// the basic class of composite target 8 | /// 9 | /// The type of the target. 10 | public abstract class CompositeTargetBase : ICompositeTarget 11 | { 12 | private Action m_Callback; 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The callback which will be invoked after the resolving is finished successfully. 18 | protected CompositeTargetBase(Action callback) 19 | { 20 | m_Callback = callback; 21 | } 22 | 23 | /// 24 | /// Resolves the specified application server. 25 | /// 26 | /// The application server. 27 | /// The export provider. 28 | /// 29 | public bool Resolve(IAppServer appServer, ExportProvider exportProvider) 30 | { 31 | TTarget result = default(TTarget); 32 | 33 | if (!TryResolve(appServer, exportProvider, out result)) 34 | return false; 35 | 36 | m_Callback(result); 37 | return true; 38 | } 39 | 40 | /// 41 | /// Tries to resolve. 42 | /// 43 | /// The application server. 44 | /// The export provider. 45 | /// The resolving result. 46 | /// 47 | protected abstract bool TryResolve(IAppServer appServer, ExportProvider exportProvider, out TTarget result); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NRack.Base/CompositeTargtes/LoggerFactoryCompositeTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Composition.Hosting; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using AnyLog; 9 | using NRack.Base.Config; 10 | 11 | namespace NRack.Base.CompositeTargets 12 | { 13 | class LoggerFactoryCompositeTarget : SingleResultCompositeTargetCore 14 | { 15 | public LoggerFactoryCompositeTarget(Action callback) 16 | : base((config) => config.LogFactory, callback, true) 17 | { 18 | 19 | } 20 | 21 | protected override bool MetadataNameEqual(ILoggerFactoryMetadata metadata, string name) 22 | { 23 | return metadata.Name.Equals(name, StringComparison.OrdinalIgnoreCase); 24 | } 25 | 26 | protected override IEnumerable> Sort(IEnumerable> factories) 27 | { 28 | return factories.OrderBy(f => f.Metadata.Priority); 29 | } 30 | 31 | protected override bool PrepareResult(ILoggerFactory result, IAppServer appServer, ILoggerFactoryMetadata metadata) 32 | { 33 | if (string.IsNullOrEmpty(metadata.ConfigFileName)) 34 | { 35 | return result.Initialize(new string[0]); 36 | } 37 | 38 | var currentAppDomain = AppDomain.CurrentDomain; 39 | var isolation = IsolationMode.None; 40 | 41 | var isolationValue = currentAppDomain.GetData(typeof(IsolationMode).Name); 42 | 43 | if (isolationValue != null) 44 | isolation = (IsolationMode)isolationValue; 45 | 46 | var configFileName = metadata.ConfigFileName; 47 | 48 | if (Path.DirectorySeparatorChar != '\\') 49 | { 50 | configFileName = Path.GetFileNameWithoutExtension(configFileName) + ".unix" + Path.GetExtension(configFileName); 51 | } 52 | 53 | var configFiles = new List(); 54 | 55 | if (isolation == IsolationMode.None) 56 | { 57 | configFiles.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configFileName)); 58 | configFiles.Add(Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config"), configFileName)); 59 | } 60 | else //The running AppServer is in isolated appdomain 61 | { 62 | configFiles.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configFileName)); 63 | configFiles.Add(Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config"), configFileName)); 64 | 65 | //go to the application's root 66 | //the appdomain's root is /WorkingDir/DomainName, so get parent path twice to reach the application root 67 | var rootDir = Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).Parent.FullName; 68 | 69 | configFiles.Add(Path.Combine(rootDir, AppDomain.CurrentDomain.FriendlyName + "." + configFileName)); 70 | configFiles.Add(Path.Combine(Path.Combine(rootDir, "Config"), AppDomain.CurrentDomain.FriendlyName + "." + configFileName)); 71 | configFiles.Add(Path.Combine(rootDir, configFileName)); 72 | configFiles.Add(Path.Combine(Path.Combine(rootDir, "Config"), configFileName)); 73 | } 74 | 75 | if (!result.Initialize(configFiles.ToArray())) 76 | { 77 | appServer.Logger.Error("Failed to initialize the logfactory:" + metadata.Name); 78 | return false; 79 | } 80 | 81 | return true; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/ConfigurationElementBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Configuration; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Xml; 8 | 9 | namespace NRack.Base.Config 10 | { 11 | /// 12 | /// ConfigurationElementBase 13 | /// 14 | [Serializable] 15 | public class ConfigurationElementBase : ConfigurationElement 16 | { 17 | private bool m_NameRequired; 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | public ConfigurationElementBase() 23 | : this(true) 24 | { 25 | 26 | } 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | /// if set to true [name required]. 32 | public ConfigurationElementBase(bool nameRequired) 33 | { 34 | m_NameRequired = nameRequired; 35 | Options = new NameValueCollection(); 36 | } 37 | 38 | /// 39 | /// Gets the name. 40 | /// 41 | [ConfigurationProperty("name")] 42 | public string Name 43 | { 44 | get { return this["name"] as string; } 45 | } 46 | 47 | /// 48 | /// Reads XML from the configuration file. 49 | /// 50 | /// The that reads from the configuration file. 51 | /// true to serialize only the collection key properties; otherwise, false. 52 | /// The element to read is locked.- or -An attribute of the current node is not recognized.- or -The lock status of the current node cannot be determined. 53 | protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey) 54 | { 55 | base.DeserializeElement(reader, serializeCollectionKey); 56 | 57 | if (m_NameRequired && string.IsNullOrEmpty(Name)) 58 | { 59 | throw new ConfigurationErrorsException("Required attribute 'name' not found."); 60 | } 61 | } 62 | 63 | /// 64 | /// Gets the options. 65 | /// 66 | public NameValueCollection Options { get; private set; } 67 | 68 | /// 69 | /// Gets a value indicating whether an unknown attribute is encountered during deserialization. 70 | /// 71 | /// The name of the unrecognized attribute. 72 | /// The value of the unrecognized attribute. 73 | /// 74 | /// true when an unknown attribute is encountered while deserializing; otherwise, false. 75 | /// 76 | protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) 77 | { 78 | Options.Add(name, value); 79 | return true; 80 | } 81 | 82 | /// 83 | /// Gets the option elements. 84 | /// 85 | public NameValueCollection OptionElements { get; private set; } 86 | 87 | /// 88 | /// Gets a value indicating whether an unknown element is encountered during deserialization. 89 | /// 90 | /// The name of the unknown subelement. 91 | /// The being used for deserialization. 92 | /// 93 | /// true when an unknown element is encountered while deserializing; otherwise, false. 94 | /// 95 | /// The element identified by is locked.- or -One or more of the element's attributes is locked.- or - is unrecognized, or the element has an unrecognized attribute.- or -The element has a Boolean attribute with an invalid value.- or -An attempt was made to deserialize a property more than once.- or -An attempt was made to deserialize a property that is not a valid member of the element.- or -The element cannot contain a CDATA or text element. 96 | protected override bool OnDeserializeUnrecognizedElement(string elementName, System.Xml.XmlReader reader) 97 | { 98 | if (OptionElements == null) 99 | OptionElements = new NameValueCollection(); 100 | 101 | OptionElements.Add(elementName, reader.ReadOuterXml()); 102 | return true; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/GenericConfigurationElementCollectionBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace NRack.Base.Config 8 | { 9 | /// 10 | /// GenericConfigurationElementCollectionBase 11 | /// 12 | /// The type of the config element. 13 | /// The type of the config interface. 14 | public class GenericConfigurationElementCollectionBase : ConfigurationElementCollection, IEnumerable 15 | where TConfigElement : ConfigurationElement, TConfigInterface, new() 16 | { 17 | /// 18 | /// Gets or sets a property, attribute, or child element of this configuration element. 19 | /// 20 | /// The specified property, attribute, or child element 21 | public TConfigElement this[int index] 22 | { 23 | get 24 | { 25 | return (TConfigElement)base.BaseGet(index); 26 | } 27 | set 28 | { 29 | if (base.BaseGet(index) != null) 30 | { 31 | base.BaseRemoveAt(index); 32 | } 33 | this.BaseAdd(index, value as ConfigurationElement); 34 | } 35 | } 36 | 37 | /// 38 | /// When overridden in a derived class, creates a new . 39 | /// 40 | /// 41 | /// A new . 42 | /// 43 | protected override ConfigurationElement CreateNewElement() 44 | { 45 | return new TConfigElement() as ConfigurationElement; 46 | } 47 | 48 | /// 49 | /// Gets the element key for a specified configuration element when overridden in a derived class. 50 | /// 51 | /// The to return the key for. 52 | /// 53 | /// An that acts as the key for the specified . 54 | /// 55 | protected override object GetElementKey(ConfigurationElement element) 56 | { 57 | return element; 58 | } 59 | 60 | #region IEnumerable[T] implementation 61 | 62 | /// 63 | /// Returns an enumerator that iterates through the collection. 64 | /// 65 | /// 66 | /// A that can be used to iterate through the collection. 67 | /// 68 | public new IEnumerator GetEnumerator() 69 | { 70 | int count = base.Count; 71 | 72 | for (int i = 0; i < count; i++) 73 | { 74 | yield return (TConfigElement)base.BaseGet(i); 75 | } 76 | } 77 | 78 | #endregion 79 | } 80 | 81 | /// 82 | /// Generic ConfigurationElement CollectionBase 83 | /// 84 | /// The type of the configuration element. 85 | public class GenericConfigurationElementCollectionBase : ConfigurationElementCollection, IEnumerable 86 | where TConfigElement : ConfigurationElement, new() 87 | { 88 | /// 89 | /// Gets or sets a property, attribute, or child element of this configuration element. 90 | /// 91 | /// The specified property, attribute, or child element 92 | public TConfigElement this[int index] 93 | { 94 | get 95 | { 96 | return (TConfigElement)base.BaseGet(index); 97 | } 98 | set 99 | { 100 | if (base.BaseGet(index) != null) 101 | { 102 | base.BaseRemoveAt(index); 103 | } 104 | this.BaseAdd(index, value as ConfigurationElement); 105 | } 106 | } 107 | 108 | /// 109 | /// When overridden in a derived class, creates a new . 110 | /// 111 | /// 112 | /// A new . 113 | /// 114 | protected override ConfigurationElement CreateNewElement() 115 | { 116 | return new TConfigElement() as ConfigurationElement; 117 | } 118 | 119 | /// 120 | /// Gets the element key for a specified configuration element when overridden in a derived class. 121 | /// 122 | /// The to return the key for. 123 | /// 124 | /// An that acts as the key for the specified . 125 | /// 126 | protected override object GetElementKey(ConfigurationElement element) 127 | { 128 | return element; 129 | } 130 | 131 | #region IEnumerable[T] implementation 132 | 133 | /// 134 | /// Returns an enumerator that iterates through the collection. 135 | /// 136 | /// 137 | /// A that can be used to iterate through the collection. 138 | /// 139 | public new IEnumerator GetEnumerator() 140 | { 141 | int count = base.Count; 142 | 143 | for (int i = 0; i < count; i++) 144 | { 145 | yield return (TConfigElement)base.BaseGet(i); 146 | } 147 | } 148 | 149 | #endregion 150 | } 151 | 152 | /// 153 | /// GenericConfigurationElementCollection 154 | /// 155 | /// The type of the config element. 156 | /// The type of the config interface. 157 | public class GenericConfigurationElementCollection : GenericConfigurationElementCollectionBase, IEnumerable 158 | where TConfigElement : ConfigurationElementBase, TConfigInterface, new() 159 | { 160 | /// 161 | /// Gets the element key. 162 | /// 163 | /// The element. 164 | /// 165 | protected override object GetElementKey(ConfigurationElement element) 166 | { 167 | return ((TConfigElement)element).Name; 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/HotUpdateAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base.Config 4 | { 5 | /// 6 | /// the attribute to mark which property of ServerConfig support hot update 7 | /// 8 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 9 | public class HotUpdateAttribute : Attribute 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/IConfigSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NRack.Base.Config 6 | { 7 | public interface IConfigSource 8 | { 9 | string LogFactory { get; } 10 | 11 | IsolationMode Isolation { get; } 12 | 13 | int StatusCollectInterval { get; } 14 | 15 | IEnumerable Servers { get; } 16 | 17 | int TcpRemotingPort { get; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/IServerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Text; 5 | 6 | namespace NRack.Base.Config 7 | { 8 | public interface IServerConfig 9 | { 10 | string Name { get; } 11 | 12 | string Group { get; } 13 | 14 | string Type { get; } 15 | 16 | string LogFactory { get; } 17 | 18 | StartupType StartupType { get; } 19 | 20 | NameValueCollection Options { get; } 21 | 22 | NameValueCollection OptionElements { get; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/NRackConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace NRack.Base.Config 6 | { 7 | #if !DOTNETCORE 8 | [Serializable] 9 | #endif 10 | public class NRackConfig : IConfigSource 11 | { 12 | public const int DefaultTcpRemotingPort = 0; 13 | 14 | public NRackConfig() 15 | { 16 | 17 | } 18 | 19 | public NRackConfig(IConfigSource configSource) 20 | { 21 | Isolation = configSource.Isolation; 22 | LogFactory = configSource.LogFactory; 23 | StatusCollectInterval = configSource.StatusCollectInterval; 24 | TcpRemotingPort = DefaultTcpRemotingPort; 25 | 26 | if (configSource.Servers != null && configSource.Servers.Any()) 27 | { 28 | this.Servers = configSource.Servers.Select(s => new ServerConfig(s)).ToArray(); 29 | } 30 | } 31 | 32 | public IsolationMode Isolation { get; set; } 33 | 34 | public IEnumerable Servers { get; set; } 35 | 36 | public string LogFactory { get; set; } 37 | 38 | public int StatusCollectInterval { get; set; } 39 | 40 | public int TcpRemotingPort { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/NRack.Base/Config/ServerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | #if !DOTNETCORE 5 | using System.Configuration; 6 | using NRack.Base.Configuration; 7 | #endif 8 | 9 | namespace NRack.Base.Config 10 | { 11 | #if !DOTNETCORE 12 | [Serializable] 13 | #endif 14 | public class ServerConfig : IServerConfig 15 | { 16 | public ServerConfig() 17 | { 18 | 19 | } 20 | 21 | public ServerConfig(IServerConfig serverConfig) 22 | { 23 | #if !DOTNETCORE 24 | serverConfig.CopyPropertiesTo(this); 25 | #endif 26 | } 27 | 28 | public string Name { get; set; } 29 | 30 | public string Group { get; set; } 31 | 32 | public string Type { get; set; } 33 | 34 | public string LogFactory { get; set; } 35 | 36 | public StartupType StartupType { get; set; } 37 | 38 | public NameValueCollection Options { get; set; } 39 | 40 | public NameValueCollection OptionElements { get; set; } 41 | 42 | #if !DOTNETCORE 43 | 44 | /// 45 | /// Gets the child config. 46 | /// 47 | /// The type of the config. 48 | /// Name of the child config. 49 | /// 50 | public virtual TConfig GetChildConfig(string childConfigName) 51 | where TConfig : ConfigurationElement, new() 52 | { 53 | return this.OptionElements.GetChildConfig(childConfigName); 54 | } 55 | #endif 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/NRack.Base/Configuration/NRackConfigSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Configuration; 5 | using System.Linq; 6 | using System.Text; 7 | using NRack.Base.Config; 8 | 9 | namespace NRack.Base.Configuration 10 | { 11 | public class NRackConfigSection : ConfigurationSection, IConfigSource 12 | { 13 | /// 14 | /// Gets the isolation mode. 15 | /// 16 | [ConfigurationProperty("isolation", IsRequired = false, DefaultValue = IsolationMode.None)] 17 | public IsolationMode Isolation 18 | { 19 | get { return (IsolationMode)this["isolation"]; } 20 | } 21 | 22 | [ConfigurationProperty("logFactory", IsRequired = false)] 23 | public string LogFactory 24 | { 25 | get { return (string)this["logFactory"]; } 26 | } 27 | 28 | [ConfigurationProperty("statusCollectInterval", IsRequired = false, DefaultValue = 60)] 29 | public int StatusCollectInterval 30 | { 31 | get { return (int)this["statusCollectInterval"]; } 32 | } 33 | 34 | [ConfigurationProperty("tcpRemotingPort", IsRequired = false, DefaultValue = NRackConfig.DefaultTcpRemotingPort)] 35 | public int TcpRemotingPort 36 | { 37 | get { return (int)this["tcpRemotingPort"]; } 38 | } 39 | 40 | /// 41 | /// Gets all the server configurations 42 | /// 43 | [ConfigurationProperty("servers")] 44 | public ServerCollection Servers 45 | { 46 | get 47 | { 48 | return this["servers"] as ServerCollection; 49 | } 50 | } 51 | 52 | IEnumerable IConfigSource.Servers 53 | { 54 | get { return this.Servers; } 55 | } 56 | 57 | /// 58 | /// Gets the option elements. 59 | /// 60 | public NameValueCollection OptionElements { get; private set; } 61 | 62 | /// 63 | /// Gets a value indicating whether an unknown element is encountered during deserialization. 64 | /// To keep compatible with old configuration 65 | /// 66 | /// The name of the unknown subelement. 67 | /// The being used for deserialization. 68 | /// 69 | /// true when an unknown element is encountered while deserializing; otherwise, false. 70 | /// 71 | /// The element identified by is locked.- or -One or more of the element's attributes is locked.- or - is unrecognized, or the element has an unrecognized attribute.- or -The element has a Boolean attribute with an invalid value.- or -An attempt was made to deserialize a property more than once.- or -An attempt was made to deserialize a property that is not a valid member of the element.- or -The element cannot contain a CDATA or text element. 72 | protected override bool OnDeserializeUnrecognizedElement(string elementName, System.Xml.XmlReader reader) 73 | { 74 | if (OptionElements == null) 75 | OptionElements = new NameValueCollection(); 76 | 77 | OptionElements.Add(elementName, reader.ReadOuterXml()); 78 | return true; 79 | } 80 | 81 | /// 82 | /// Gets a value indicating whether an unknown attribute is encountered during deserialization. 83 | /// 84 | /// The name of the unrecognized attribute. 85 | /// The value of the unrecognized attribute. 86 | /// 87 | /// true when an unknown attribute is encountered while deserializing; otherwise, false. 88 | /// 89 | protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) 90 | { 91 | const string xmlns = "xmlns"; 92 | const string xmlnsPrefix = "xmlns:"; 93 | const string xsiPrefix = "xsi:"; 94 | 95 | //for configuration intellisense, allow these unrecognized attributes: xmlns, xmlns:*, xsi:* 96 | if (name.Equals(xmlns) || name.StartsWith(xmlnsPrefix) || name.StartsWith(xsiPrefix)) 97 | return true; 98 | 99 | return false; 100 | } 101 | 102 | /// 103 | /// Gets the child config. 104 | /// 105 | /// The type of the config. 106 | /// Name of the child config. 107 | /// 108 | public TConfig GetChildConfig(string childConfigName) 109 | where TConfig : ConfigurationElement, new() 110 | { 111 | return this.OptionElements.GetChildConfig(childConfigName); 112 | } 113 | } 114 | 115 | /// 116 | /// Server configuration collection 117 | /// 118 | [ConfigurationCollection(typeof(ServerConfigElement), AddItemName = "server")] 119 | public class ServerCollection : GenericConfigurationElementCollection 120 | { 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/NRack.Base/Configuration/ServerConfigElement.cs: -------------------------------------------------------------------------------- 1 | using NRack.Base.Config; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Configuration; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace NRack.Base.Configuration 9 | { 10 | public class ServerConfigElement : ConfigurationElementBase, IServerConfig 11 | { 12 | [ConfigurationProperty("group", IsRequired = false)] 13 | public string Group 14 | { 15 | get { return this["group"] as string; } 16 | } 17 | 18 | [ConfigurationProperty("type", IsRequired = false)] 19 | public string Type 20 | { 21 | get { return this["type"] as string; } 22 | } 23 | 24 | [ConfigurationProperty("logFactory", IsRequired = false)] 25 | public string LogFactory 26 | { 27 | get { return this["logFactory"] as string; } 28 | } 29 | 30 | [ConfigurationProperty("startupType", IsRequired = false)] 31 | public StartupType StartupType 32 | { 33 | get { return (StartupType)this["startupType"]; } 34 | } 35 | 36 | /// 37 | /// Gets the child config. 38 | /// 39 | /// The type of the config. 40 | /// Name of the child config. 41 | /// 42 | public TConfig GetChildConfig(string childConfigName) 43 | where TConfig : ConfigurationElement, new() 44 | { 45 | return this.OptionElements.GetChildConfig(childConfigName); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/NRack.Base/DotNetCore/CompositionContainer.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.ComponentModel.Composition.Hosting; 3 | 4 | namespace System.ComponentModel.Composition 5 | { 6 | public class CompositionContainer : ExportProvider 7 | { 8 | 9 | } 10 | } -------------------------------------------------------------------------------- /src/NRack.Base/DotNetCore/ExportProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace System.ComponentModel.Composition.Hosting 4 | { 5 | public class ExportProvider 6 | { 7 | public IEnumerable> GetExports() 8 | { 9 | throw new NotImplementedException(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/NRack.Base/DotNetCore/FakeAttributes.cs: -------------------------------------------------------------------------------- 1 | namespace System.Runtime.Serialization 2 | { 3 | [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Property)] 4 | public class SerializableAttribute : Attribute 5 | { 6 | 7 | } 8 | 9 | public class NonSerializedAttribute : Attribute 10 | { 11 | 12 | } 13 | 14 | [AttributeUsageAttribute(AttributeTargets.Method)] 15 | public class OnSerializingAttribute : Attribute 16 | { 17 | 18 | } 19 | 20 | [AttributeUsageAttribute(AttributeTargets.Method)] 21 | public class OnDeserializedAttribute : Attribute 22 | { 23 | 24 | } 25 | 26 | public class StreamingContext 27 | { 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /src/NRack.Base/DotNetCore/LoggingExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Microsoft.Extensions.Logging 5 | { 6 | public static class LoggingExtensions 7 | { 8 | public static void ErrorFormat(this ILogger logger, string message, params string[] args) 9 | { 10 | logger.LogError(null, message, args); 11 | } 12 | 13 | public static void Error(this ILogger logger, string message, Exception e) 14 | { 15 | logger.LogError(null, e, message); 16 | } 17 | 18 | public static void Error(this ILogger logger, string message) 19 | { 20 | logger.LogError(null, message); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/NRack.Base/ErrorEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base 4 | { 5 | public class ErrorEventArgs : EventArgs 6 | { 7 | public Exception Exception { get; private set; } 8 | 9 | public ErrorEventArgs(Exception exception) 10 | { 11 | Exception = exception; 12 | } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/NRack.Base/IAppEndPoint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base 4 | { 5 | /// 6 | /// The interface which can abtract the absolute address of one application instance in the whole system 7 | /// 8 | public interface IAppEndPoint 9 | { 10 | /// 11 | /// Gets the identity of one application instance. 12 | /// 13 | /// 14 | /// The identity. 15 | /// 16 | object Identity { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NRack.Base/IAppServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | #if DOTNETCORE 4 | using ILog = Microsoft.Extensions.Logging.ILogger; 5 | #else 6 | using AnyLog; 7 | #endif 8 | 9 | 10 | namespace NRack.Base 11 | { 12 | public interface IAppServer : IManagedApp 13 | { 14 | ILog Logger { get; } 15 | 16 | IAppEndPoint EndPoint { get; } 17 | 18 | IMessageBus MessageBus { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NRack.Base/IBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NRack.Base 5 | { 6 | public interface IBootstrap 7 | { 8 | /// 9 | /// Initializes this instance. 10 | /// 11 | /// 12 | bool Initialize(); 13 | 14 | /// 15 | /// Gets all the app servers running in this bootstrap 16 | /// 17 | IEnumerable AppServers { get; } 18 | 19 | /// 20 | /// Starts this instance. 21 | /// 22 | void Start(); 23 | 24 | /// 25 | /// Stops this instance. 26 | /// 27 | void Stop(); 28 | 29 | /// 30 | /// Gets the configuration file path. 31 | /// 32 | /// 33 | /// The configuration file path. 34 | /// 35 | string ConfigFilePath { get; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NRack.Base/ICompositeTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Composition.Hosting; 3 | 4 | namespace NRack.Base 5 | { 6 | /// 7 | /// The interface for the composite target 8 | /// 9 | public interface ICompositeTarget 10 | { 11 | /// 12 | /// Resolves the specified application server. 13 | /// 14 | /// The application server. 15 | /// The export provider. 16 | /// 17 | bool Resolve(IAppServer appServer, ExportProvider exportProvider); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NRack.Base/IManagedApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NRack.Base.Config; 3 | using NRack.Base.Metadata; 4 | 5 | namespace NRack.Base 6 | { 7 | public interface IManagedApp : IManagedAppBase 8 | { 9 | string Name { get; } 10 | 11 | bool Setup(IBootstrap bootstrap, IServerConfig config); 12 | 13 | ServerState State { get; } 14 | 15 | IServerConfig Config { get; } 16 | } 17 | 18 | public interface IManagedAppBase 19 | { 20 | AppServerMetadata GetMetadata(); 21 | 22 | bool Start(); 23 | 24 | void Stop(); 25 | 26 | bool CanBeRecycled(); 27 | 28 | StatusInfoCollection CollectStatus(); 29 | 30 | void ReportPotentialConfigChange(IServerConfig config); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NRack.Base/IMessageBus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base 4 | { 5 | /// 6 | /// NRack message bus interface 7 | /// 8 | public interface IMessageBus 9 | { 10 | /// 11 | /// Sends message of one specific topic to the specific receiver. 12 | /// 13 | /// The receiver. 14 | /// The topic. 15 | /// The message. 16 | void Send(IAppEndPoint receiver, string topic, object message); 17 | 18 | /// 19 | /// Sends message of one specific topic to global system. 20 | /// 21 | /// The topic. 22 | /// The message. 23 | void Send(string topic, object message); 24 | 25 | /// 26 | /// Register the topic message handler. 27 | /// 28 | /// 29 | /// The toppic. 30 | /// The topic handler. 31 | void On(string toppic, Action topicHandler); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NRack.Base/IStatusCollector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | #if DOTNETCORE 4 | using ILog = Microsoft.Extensions.Logging.ILogger; 5 | #else 6 | using AnyLog; 7 | #endif 8 | 9 | namespace NRack.Base 10 | { 11 | public class AppServerStatus 12 | { 13 | public AppServerMetadata Metadata { get; private set; } 14 | 15 | public StatusInfoCollection DataCollection { get; private set; } 16 | 17 | public AppServerStatus(AppServerMetadata metadata, StatusInfoCollection dataCollection) 18 | { 19 | Metadata = metadata; 20 | DataCollection = dataCollection; 21 | } 22 | } 23 | 24 | public interface IStatusCollector 25 | { 26 | void Collect(AppServerStatus bootstrapStatus, IEnumerable appStatusList, ILog logger); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NRack.Base/IsolationMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base 4 | { 5 | /// 6 | /// AppServer instance running isolation mode 7 | /// 8 | public enum IsolationMode 9 | { 10 | /// 11 | /// No isolation 12 | /// 13 | None, 14 | /// 15 | /// Isolation by AppDomain 16 | /// 17 | AppDomain, 18 | 19 | /// 20 | /// Isolation by process 21 | /// 22 | Process 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NRack.Base/Metadata/AppServerMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Runtime.Serialization; 5 | using NRack.Base.Metadata; 6 | 7 | namespace NRack.Base 8 | { 9 | [Serializable] 10 | public class AppServerMetadata 11 | { 12 | public AppServerMetadata() 13 | { 14 | 15 | } 16 | 17 | public AppServerMetadata(IAppServerMetadata attribute, Type appType) 18 | { 19 | Name = attribute.Name; 20 | AppType = appType.AssemblyQualifiedName; 21 | StatusFields = StatusInfoAttribute.GetFromType(attribute.GetType()).ToArray(); 22 | } 23 | 24 | public static AppServerMetadata GetAppServerMetadata(Type serverType) 25 | { 26 | if (serverType == null) 27 | throw new ArgumentNullException("serverType"); 28 | 29 | var topType = serverType; 30 | 31 | var attType = typeof(AppServerMetadataAttribute); 32 | 33 | while (true) 34 | { 35 | var atts = serverType.GetCustomAttributes(attType, false); 36 | 37 | if (atts != null && atts.Length > 0) 38 | { 39 | var metatdata = atts[0] as AppServerMetadataAttribute; 40 | return new AppServerMetadata(metatdata, topType); 41 | } 42 | 43 | var baseType = serverType.GetBaseType(); 44 | 45 | if (baseType == null) 46 | return null; 47 | 48 | serverType = baseType; 49 | } 50 | } 51 | 52 | #region IAppServerMetadata implementation 53 | 54 | public string Name { get; set; } 55 | 56 | public string AppType { get; set; } 57 | 58 | public StatusInfoAttribute[] StatusFields { get; set; } 59 | 60 | #endregion 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/NRack.Base/Metadata/AppServerMetadataAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | #if DOTNETCORE 5 | using System.Composition; 6 | #else 7 | using System.ComponentModel.Composition; 8 | #endif 9 | 10 | 11 | namespace NRack.Base.Metadata 12 | { 13 | [Serializable] 14 | [MetadataAttribute] 15 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 16 | [StatusInfo(StatusInfoKeys.IsRunning, Name = "Is Running", DataType = typeof(bool), Order = 100)] 17 | public class AppServerMetadataAttribute : ExportAttribute, IAppServerMetadata 18 | { 19 | public string Name { get; set; } 20 | 21 | public AppServerMetadataAttribute() 22 | : base(typeof(IAppServer)) 23 | { 24 | 25 | } 26 | 27 | public AppServerMetadataAttribute(string name) 28 | : this() 29 | { 30 | Name = name; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NRack.Base/Metadata/IAppServerMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace NRack.Base.Metadata 5 | { 6 | public interface IAppServerMetadata 7 | { 8 | string Name { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NRack.Base/Metadata/StatusInfoAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | namespace NRack.Base.Metadata 8 | { 9 | /// 10 | /// StatusInfo Metadata 11 | /// 12 | #if !SILVERLIGHT 13 | [Serializable] 14 | #endif 15 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 16 | public class StatusInfoAttribute : Attribute 17 | { 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | public StatusInfoAttribute() 22 | { 23 | OutputInLog = true; 24 | } 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// 29 | /// The key. 30 | public StatusInfoAttribute(string key) 31 | : this() 32 | { 33 | Key = key; 34 | } 35 | 36 | /// 37 | /// Gets or sets the key. 38 | /// 39 | /// 40 | /// The key. 41 | /// 42 | public string Key { get; set; } 43 | 44 | /// 45 | /// Gets or sets the name. 46 | /// 47 | /// 48 | /// The name. 49 | /// 50 | public string Name { get; set; } 51 | 52 | /// 53 | /// Gets or sets the short name. 54 | /// 55 | /// 56 | /// The short name. 57 | /// 58 | public string ShortName { get; set; } 59 | 60 | /// 61 | /// Gets or sets the format. 62 | /// 63 | /// 64 | /// The format. 65 | /// 66 | public string Format { get; set; } 67 | 68 | /// 69 | /// Gets or sets the order. 70 | /// 71 | /// 72 | /// The order. 73 | /// 74 | public int Order { get; set; } 75 | 76 | 77 | /// 78 | /// Gets or sets a value indicating whether [output in log]. 79 | /// 80 | /// 81 | /// true if [output in log]; otherwise, false. 82 | /// 83 | public bool OutputInLog { get; set; } 84 | 85 | /// 86 | /// Gets or sets the type of the data. 87 | /// 88 | /// 89 | /// The type of the data. 90 | /// 91 | public Type DataType { get; set; } 92 | 93 | public static IEnumerable GetFromType(Type type) 94 | { 95 | return type.GetCustomAttributes(typeof(StatusInfoAttribute), true).OfType(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/NRack.Base/Metadata/StatusInfoKeys.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace NRack.Base.Metadata 7 | { 8 | /// 9 | /// Server StatusInfo Metadata 10 | /// 11 | public class StatusInfoKeys 12 | { 13 | #region Shared 14 | 15 | /// 16 | /// The cpu usage 17 | /// 18 | public const string CpuUsage = "CpuUsage"; 19 | 20 | /// 21 | /// The memory usage 22 | /// 23 | public const string MemoryUsage = "MemoryUsage"; 24 | 25 | /// 26 | /// The total thread count 27 | /// 28 | public const string TotalThreadCount = "TotalThreadCount"; 29 | 30 | /// 31 | /// The available working threads count 32 | /// 33 | public const string AvailableWorkingThreads = "AvailableWorkingThreads"; 34 | 35 | /// 36 | /// The available completion port threads count 37 | /// 38 | public const string AvailableCompletionPortThreads = "AvailableCompletionPortThreads"; 39 | 40 | /// 41 | /// The max working threads count 42 | /// 43 | public const string MaxWorkingThreads = "MaxWorkingThreads"; 44 | 45 | /// 46 | /// The max completion port threads count 47 | /// 48 | public const string MaxCompletionPortThreads = "MaxCompletionPortThreads"; 49 | 50 | #endregion 51 | 52 | #region For server instance 53 | /// 54 | /// true if this instance is running; otherwise, false. 55 | /// 56 | public const string IsRunning = "IsRunning"; 57 | 58 | #endregion 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/NRack.Base/NRack.Base.Net45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 8 | Library 9 | Properties 10 | NRack.Base 11 | NRack.Base 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\net45\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | false 25 | 26 | 27 | pdbonly 28 | true 29 | bin\net45\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | false 34 | 35 | 36 | 37 | ..\packages\AnyLog.0.1.8\lib\net45\AnyLog.dll 38 | True 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | GlobalAssemblyInfo.cs 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | -------------------------------------------------------------------------------- /src/NRack.Base/NRack.Base.NetCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.3 5 | NRack.Base 6 | Library 7 | NRack.Base 8 | $(PackageTargetFallback);portable-net45+win8 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | $(DefineConstants);DOTNETCORE 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/NRack.Base/NRack.Base.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 8 | Library 9 | Properties 10 | NRack.Base 11 | NRack.Base 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\net40\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\net40\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\packages\AnyLog.0.1.8\lib\net40\AnyLog.dll 36 | True 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | GlobalAssemblyInfo.cs 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 99 | -------------------------------------------------------------------------------- /src/NRack.Base/NRack.Base.csproj.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NDock.Base.csproj 5 | 1.0.0 6 | Kerry 7 | Kerry 8 | http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE 9 | http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE 10 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE 11 | false 12 | Package description 13 | Summary of changes made in this release of the package. 14 | Copyright 2015 15 | Tag1 Tag2 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/NRack.Base/NRackEnv.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base 4 | { 5 | /// 6 | /// System environment variables of NRack 7 | /// 8 | public static class NRackEnv 9 | { 10 | /// 11 | /// Is this runtime Mono 12 | /// 13 | public static readonly bool IsMono; 14 | 15 | static NRackEnv() 16 | { 17 | // detect the runtime by the type Mono.Runtime 18 | IsMono = Type.GetType("Mono.Runtime") != null; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NRack.Base/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("NRack.Base")] 9 | [assembly: AssemblyDescription("NRack.Base")] 10 | [assembly: AssemblyConfiguration("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("c9a0102b-2f59-4299-839c-bae1c3a02b93")] 19 | -------------------------------------------------------------------------------- /src/NRack.Base/Provider/IProviderMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NRack.Base.Provider 4 | { 5 | /// 6 | /// The provider metadata interface 7 | /// 8 | public interface IProviderMetadata 9 | { 10 | /// 11 | /// Gets the name. 12 | /// 13 | /// 14 | /// The name. 15 | /// 16 | string Name { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NRack.Base/Provider/ProviderMetadataAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | #if DOTNETCORE 3 | using System.Composition; 4 | #else 5 | using System.ComponentModel.Composition; 6 | #endif 7 | 8 | namespace NRack.Base.Provider 9 | { 10 | [MetadataAttribute] 11 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 12 | public class ProviderMetadataAttribute : ExportAttribute, IProviderMetadata 13 | { 14 | public string Name { get; private set; } 15 | 16 | public ProviderMetadataAttribute(string name) 17 | { 18 | Name = name; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NRack.Base/ServerState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace NRack.Base 5 | { 6 | /// 7 | /// Server's state enum class 8 | /// 9 | public enum ServerState : int 10 | { 11 | /// 12 | /// Not initialized 13 | /// 14 | NotInitialized = ServerStateConst.NotInitialized, 15 | 16 | /// 17 | /// In initializing 18 | /// 19 | Initializing = ServerStateConst.Initializing, 20 | 21 | /// 22 | /// Has been initialized, but not started 23 | /// 24 | NotStarted = ServerStateConst.NotStarted, 25 | 26 | /// 27 | /// In starting 28 | /// 29 | Starting = ServerStateConst.Starting, 30 | 31 | /// 32 | /// In running 33 | /// 34 | Running = ServerStateConst.Running, 35 | 36 | /// 37 | /// In stopping 38 | /// 39 | Stopping = ServerStateConst.Stopping, 40 | } 41 | 42 | internal class ServerStateConst 43 | { 44 | public const int NotInitialized = 0; 45 | 46 | public const int Initializing = 1; 47 | 48 | public const int NotStarted = 2; 49 | 50 | public const int Starting = 3; 51 | 52 | public const int Running = 4; 53 | 54 | public const int Stopping = 5; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/NRack.Base/StartupType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace NRack.Base 5 | { 6 | /// 7 | /// Startup type 8 | /// 9 | public enum StartupType 10 | { 11 | /// 12 | /// Automatic 13 | /// 14 | Automatic, 15 | 16 | /// 17 | /// Manual 18 | /// 19 | Manual, 20 | 21 | /// 22 | /// Disabled 23 | /// 24 | Disabled 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NRack.Base/StatusInfoCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace NRack.Base 9 | { 10 | /// 11 | /// Status information collection 12 | /// 13 | [Serializable] 14 | public class StatusInfoCollection 15 | { 16 | public StatusInfoCollection() 17 | { 18 | 19 | } 20 | 21 | public StatusInfoCollection(string name) 22 | : this(name, name) 23 | { 24 | 25 | } 26 | 27 | public StatusInfoCollection(string name, string tag) 28 | { 29 | Name = name; 30 | Tag = tag; 31 | } 32 | 33 | [NonSerialized] 34 | private Dictionary m_Values = new Dictionary(); 35 | 36 | 37 | /// 38 | /// Gets the values. 39 | /// 40 | /// 41 | /// The values. 42 | /// 43 | public Dictionary Values 44 | { 45 | get { return m_Values; } 46 | } 47 | 48 | /// 49 | /// Gets or sets the name. 50 | /// 51 | /// 52 | /// The name. 53 | /// 54 | public string Name { get; set; } 55 | 56 | 57 | /// 58 | /// Gets or sets the tag. 59 | /// 60 | /// 61 | /// The tag. 62 | /// 63 | public string Tag { get; set; } 64 | 65 | /// 66 | /// Gets or sets the started time. 67 | /// 68 | /// 69 | /// The started time. 70 | /// 71 | public DateTime? StartedTime { get; set; } 72 | 73 | /// 74 | /// Gets or sets the collected time. 75 | /// 76 | /// 77 | /// The collected time. 78 | /// 79 | public DateTime CollectedTime { get; set; } 80 | 81 | /// 82 | /// Gets or sets the with the specified name. 83 | /// 84 | /// 85 | /// The . 86 | /// 87 | /// The name. 88 | /// 89 | public object this[string name] 90 | { 91 | get 92 | { 93 | object value; 94 | 95 | if (m_Values.TryGetValue(name, out value)) 96 | return value; 97 | 98 | return null; 99 | } 100 | set 101 | { 102 | m_Values[name] = value; 103 | } 104 | } 105 | 106 | /// 107 | /// Gets the value. 108 | /// 109 | /// 110 | /// The name. 111 | /// The default value. 112 | /// 113 | public T GetValue(string name, T defaultValue) 114 | where T : struct 115 | { 116 | object value; 117 | 118 | if (m_Values.TryGetValue(name, out value)) 119 | return (T)value; 120 | 121 | return defaultValue; 122 | } 123 | 124 | private List> m_InternalList; 125 | 126 | [OnSerializing] 127 | private void OnSerializing(StreamingContext context) 128 | { 129 | m_InternalList = new List>(m_Values.Count); 130 | 131 | foreach (var entry in m_Values) 132 | { 133 | m_InternalList.Add(new KeyValuePair(entry.Key, entry.Value)); 134 | } 135 | } 136 | 137 | [OnDeserialized] 138 | private void OnDeserialized(StreamingContext context) 139 | { 140 | if (m_InternalList == null || m_InternalList.Count <= 0) 141 | return; 142 | 143 | if (m_Values == null) 144 | m_Values = new Dictionary(); 145 | 146 | foreach (var entry in m_InternalList) 147 | { 148 | m_Values.Add(entry.Key, entry.Value); 149 | } 150 | 151 | m_InternalList = null; 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/NRack.Base/packages.NRack.Base.Net45.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/NRack.Base/packages.NRack.Base.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/NRack.Server/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/NRack.Server/BootstrapFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | using NRack.Base; 7 | using NRack.Base.Config; 8 | using NRack.Server.Isolation.AppDomainIsolation; 9 | using NRack.Server.Isolation.ProcessIsolation; 10 | 11 | namespace NRack.Server 12 | { 13 | /// 14 | /// Bootstrap Factory 15 | /// 16 | public static class BootstrapFactory 17 | { 18 | /// 19 | /// Creates the bootstrap. 20 | /// 21 | /// The config. 22 | /// 23 | public static IBootstrap CreateBootstrap(IConfigSource config) 24 | { 25 | if (config == null) 26 | throw new ArgumentNullException("config"); 27 | 28 | if (config.Isolation == IsolationMode.AppDomain) 29 | return new AppDomainBootstrap(config); 30 | else if (config.Isolation == IsolationMode.Process) 31 | return new ProcessBootstrap(config); 32 | else 33 | return new DefaultBootstrap(config); 34 | } 35 | 36 | /// 37 | /// Creates the bootstrap from app configuration's socketServer section. 38 | /// 39 | /// 40 | public static IBootstrap CreateBootstrap() 41 | { 42 | var configSection = ConfigurationManager.GetSection("nrack"); 43 | 44 | if (configSection == null) 45 | throw new ConfigurationErrorsException("Missing 'nrack' configuration section."); 46 | 47 | var configSource = configSection as IConfigSource; 48 | if (configSource == null) 49 | throw new ConfigurationErrorsException("Invalid 'nrack' configuration section."); 50 | 51 | return CreateBootstrap(configSource); 52 | } 53 | 54 | /// 55 | /// Creates the bootstrap from configuration file. 56 | /// 57 | /// The configuration file. 58 | /// 59 | public static IBootstrap CreateBootstrapFromConfigFile(string configFile) 60 | { 61 | ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); 62 | fileMap.ExeConfigFilename = configFile; 63 | 64 | var config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); 65 | 66 | var configSection = config.GetSection("nrack"); 67 | 68 | if (configSection == null) 69 | throw new ConfigurationErrorsException("Missing 'nrack' configuration section."); 70 | 71 | var configSource = configSection as IConfigSource; 72 | if (configSource == null) 73 | throw new ConfigurationErrorsException("Invalid 'nrack' configuration section."); 74 | 75 | return CreateBootstrap(configSource); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/NRack.Server/Config/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/NRack.Server/Config/nlog.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 11 | 17 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/NRack.Server/ConfigurationWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.IO; 5 | using System.Linq; 6 | using AnyLog; 7 | using NRack.Base; 8 | using NRack.Base.Config; 9 | 10 | namespace NRack.Server 11 | { 12 | /// 13 | /// The configuration file watcher, it is used for hot configuration updating 14 | /// 15 | public static class ConfigurationWatcher 16 | { 17 | private static FileSystemWatcher m_Watcher; 18 | 19 | private static DateTime m_LastUpdatedTime; 20 | 21 | /// 22 | /// Watches the specified configuration section. 23 | /// 24 | /// The configuration section. 25 | /// The bootstrap. 26 | public static void Watch(ConfigurationSection configSection, IBootstrap bootstrap) 27 | { 28 | if (configSection == null) 29 | throw new ArgumentNullException("configSection"); 30 | 31 | if (bootstrap == null) 32 | throw new ArgumentNullException("bootstrap"); 33 | 34 | var sectionName = configSection.SectionInformation.Name; 35 | 36 | var configSourceFile = bootstrap.ConfigFilePath; 37 | 38 | if (string.IsNullOrEmpty(configSourceFile)) 39 | throw new Exception("Cannot get your configuration file's location."); 40 | 41 | m_Watcher = new FileSystemWatcher(Path.GetDirectoryName(configSourceFile), Path.GetFileName(configSourceFile)); 42 | m_Watcher.IncludeSubdirectories = false; 43 | m_Watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size; 44 | m_Watcher.Changed += (s, e) => 45 | { 46 | var filePath = e.FullPath; 47 | 48 | if (!NeedsLoadConfig(filePath)) 49 | return; 50 | 51 | lock (m_Watcher) 52 | { 53 | if (!NeedsLoadConfig(filePath)) 54 | return; 55 | 56 | OnConfigFileUpdated(filePath, sectionName, bootstrap); 57 | m_LastUpdatedTime = DateTime.Now; 58 | } 59 | }; 60 | 61 | m_Watcher.EnableRaisingEvents = true; 62 | } 63 | 64 | internal static void Pause() 65 | { 66 | m_Watcher.EnableRaisingEvents = false; 67 | } 68 | 69 | internal static void Resume() 70 | { 71 | m_Watcher.EnableRaisingEvents = true; 72 | } 73 | 74 | private static bool NeedsLoadConfig(string filePath) 75 | { 76 | return File.GetLastWriteTime(filePath) > m_LastUpdatedTime; 77 | } 78 | 79 | private static void OnConfigFileUpdated(string filePath, string sectionName, IBootstrap bootstrap) 80 | { 81 | var fileMap = new ExeConfigurationFileMap(); 82 | fileMap.ExeConfigFilename = filePath; 83 | 84 | System.Configuration.Configuration config; 85 | 86 | try 87 | { 88 | config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); 89 | } 90 | catch(Exception e) 91 | { 92 | var loggerProvider = bootstrap as ILoggerProvider; 93 | 94 | if (loggerProvider != null) 95 | { 96 | var logger = loggerProvider.Logger; 97 | 98 | if (logger != null) 99 | logger.Error("Configuraton loading error.", e); 100 | } 101 | 102 | return; 103 | } 104 | 105 | var configSource = config.GetSection(sectionName) as IConfigSource; 106 | 107 | if (configSource == null) 108 | return; 109 | 110 | foreach (var serverConfig in configSource.Servers) 111 | { 112 | var server = bootstrap.AppServers.FirstOrDefault(x => 113 | x.Name.Equals(serverConfig.Name, StringComparison.OrdinalIgnoreCase)); 114 | 115 | if (server == null) 116 | continue; 117 | 118 | server.ReportPotentialConfigChange(new ServerConfig(serverConfig)); 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/NRack.Server/ControlCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NRack.Base; 6 | 7 | namespace NRack.Server 8 | { 9 | class ControlCommand 10 | { 11 | public string Name { get; set; } 12 | 13 | public string Description { get; set; } 14 | 15 | public Func Handler { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NRack.Server/DefaultBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Composition.Hosting; 4 | using System.Linq; 5 | using System.Text; 6 | using NRack.Base; 7 | using NRack.Base.Config; 8 | using NRack.Base.Metadata; 9 | 10 | namespace NRack.Server 11 | { 12 | [StatusInfo(StatusInfoKeys.CpuUsage, Name = "CPU Usage", Format = "{0:0.00}%", DataType = typeof(double), Order = 112)] 13 | [StatusInfo(StatusInfoKeys.MemoryUsage, Name = "Physical Memory Usage", Format = "{0:N}", DataType = typeof(double), Order = 113)] 14 | [StatusInfo(StatusInfoKeys.TotalThreadCount, Name = "Total Thread Count", Format = "{0}", DataType = typeof(double), Order = 114)] 15 | [StatusInfo(StatusInfoKeys.AvailableWorkingThreads, Name = "Available Working Threads", Format = "{0}", DataType = typeof(double), Order = 512)] 16 | [StatusInfo(StatusInfoKeys.AvailableCompletionPortThreads, Name = "Available Completion Port Threads", Format = "{0}", DataType = typeof(double), Order = 513)] 17 | [StatusInfo(StatusInfoKeys.MaxWorkingThreads, Name = "Maximum Working Threads", Format = "{0}", DataType = typeof(double), Order = 513)] 18 | [StatusInfo(StatusInfoKeys.MaxCompletionPortThreads, Name = "Maximum Completion Port Threads", Format = "{0}", DataType = typeof(double), Order = 514)] 19 | public class DefaultBootstrap : BootstrapBase 20 | { 21 | public DefaultBootstrap(IConfigSource configSource) 22 | : base(configSource) 23 | { 24 | 25 | } 26 | 27 | protected override IManagedApp CreateAppInstanceByMetadata(AppServerMetadata metadata) 28 | { 29 | return (IManagedApp)Activator.CreateInstance(Type.GetType(metadata.AppType, true, true)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NRack.Server/DefaultStatusCollector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Composition; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using AnyLog; 8 | using NRack.Base; 9 | using NRack.Base.Provider; 10 | 11 | namespace NRack.Server 12 | { 13 | [Export(typeof(IStatusCollector))] 14 | [ProviderMetadata("DefaultStatusCollector")] 15 | class DefaultStatusCollector : IStatusCollector 16 | { 17 | private void CollectAppServer(AppServerStatus app, StringBuilder sb) 18 | { 19 | var meta = app.Metadata; 20 | var status = app.DataCollection; 21 | 22 | sb.AppendLine(string.Format("{0} ----------------------------------", status.Name)); 23 | 24 | foreach (var info in meta.StatusFields) 25 | { 26 | var infoValue = status[info.Key]; 27 | 28 | if (infoValue == null) 29 | continue; 30 | 31 | sb.AppendLine(string.Format("{0}: {1}", info.Name, 32 | string.IsNullOrEmpty(info.Format) ? infoValue : string.Format(info.Format, infoValue))); 33 | } 34 | } 35 | 36 | public void Collect(AppServerStatus bootstrapStatus, IEnumerable appStatusList, ILog logger) 37 | { 38 | var sb = new StringBuilder(); 39 | 40 | CollectAppServer(bootstrapStatus, sb); 41 | 42 | foreach (var app in appStatusList) 43 | { 44 | CollectAppServer(app, sb); 45 | } 46 | 47 | logger.Info(sb.ToString()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/NRack.Server/IRemoteManagedApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NRack.Base; 6 | using NRack.Base.Config; 7 | 8 | namespace NRack.Server 9 | { 10 | /// 11 | /// IRemoteManagedApp 12 | /// 13 | public interface IRemoteManagedApp : IManagedAppBase 14 | { 15 | /// 16 | /// Setups with the specified config. 17 | /// 18 | /// Type of the server. 19 | /// The bootstrap URI. 20 | /// The assembly import root. 21 | /// The config. 22 | /// The startup configuration file path. 23 | /// 24 | bool Setup(string serverType, string bootstrapUri, string assemblyImportRoot, IServerConfig config, string startupConfigFile); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/AppAssemblyUpdateState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace NRack.Server.Isolation 9 | { 10 | class AppAssemblyUpdateState 11 | { 12 | public DateTime CurrentAssemblyTime { get; private set; } 13 | 14 | public DateTime LastUpdatedTime { get; private set; } 15 | 16 | public DateTime LastCheckTime { get; set; } 17 | 18 | private string m_AppAssemblyDir; 19 | 20 | public AppAssemblyUpdateState(string dir) 21 | { 22 | m_AppAssemblyDir = dir; 23 | CurrentAssemblyTime = LastUpdatedTime = GetLastUpdateTime(); 24 | } 25 | 26 | private DateTime GetLastUpdateTime() 27 | { 28 | var lastUpdatedTime = DateTime.MinValue; 29 | 30 | foreach(var file in Directory.GetFiles(m_AppAssemblyDir, "*.dll").Union(Directory.GetFiles(m_AppAssemblyDir, "*.exe"))) 31 | { 32 | var fileWriteTime = File.GetLastWriteTime(file); 33 | 34 | if (fileWriteTime > lastUpdatedTime) 35 | lastUpdatedTime = fileWriteTime; 36 | } 37 | 38 | return lastUpdatedTime; 39 | } 40 | 41 | public bool TryCheckUpdate() 42 | { 43 | var lastUpdatedTime = GetLastUpdateTime(); 44 | 45 | if (lastUpdatedTime <= LastUpdatedTime) 46 | return false; 47 | 48 | LastUpdatedTime = lastUpdatedTime; 49 | LastCheckTime = DateTime.Now; 50 | return true; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/AppDomainIsolation/AppDomainApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using NRack.Base; 9 | using NRack.Base.Config; 10 | using NRack.Base.Metadata; 11 | using NRack.Server.Isolation; 12 | using System.Diagnostics; 13 | 14 | namespace NRack.Server.Isolation.AppDomainIsolation 15 | { 16 | [StatusInfo(StatusInfoKeys.CpuUsage, Name = "CPU Usage", Format = "{0:0.00}%", DataType = typeof(double), Order = 112)] 17 | [StatusInfo(StatusInfoKeys.MemoryUsage, Name = "Memory Usage", Format = "{0:N}", DataType = typeof(double), Order = 113)] 18 | class AppDomainApp : IsolationApp 19 | { 20 | private AppDomain m_HostDomain; 21 | 22 | private readonly static bool m_AppDomainMonitoringSupported = false; 23 | 24 | static AppDomainApp() 25 | { 26 | try 27 | { 28 | AppDomain.MonitoringIsEnabled = true; 29 | m_AppDomainMonitoringSupported = true; 30 | } 31 | catch (NotImplementedException) 32 | { 33 | return; 34 | } 35 | } 36 | 37 | public AppDomainApp(AppServerMetadata metadata, string startupConfigFile) 38 | : base(metadata, startupConfigFile) 39 | { 40 | 41 | } 42 | 43 | private AppDomain CreateHostAppDomain() 44 | { 45 | var currentDomain = AppDomain.CurrentDomain; 46 | 47 | var startupConfigFile = StartupConfigFile; 48 | 49 | if (!string.IsNullOrEmpty(startupConfigFile)) 50 | { 51 | if (!Path.IsPathRooted(startupConfigFile)) 52 | startupConfigFile = Path.Combine(currentDomain.BaseDirectory, startupConfigFile); 53 | } 54 | 55 | var setupInfo = new AppDomainSetup 56 | { 57 | ApplicationName = Name, 58 | ApplicationBase = AppWorkingDir, 59 | ConfigurationFile = startupConfigFile, 60 | ShadowCopyFiles = "true", 61 | CachePath = Path.Combine(currentDomain.BaseDirectory, IsolationAppConst.ShadowCopyDir) 62 | }; 63 | 64 | var hostAppDomain = AppDomain.CreateDomain(Name, currentDomain.Evidence, setupInfo); 65 | 66 | var assemblyImportType = typeof(AssemblyImport); 67 | 68 | hostAppDomain.CreateInstanceFrom(assemblyImportType.Assembly.CodeBase, 69 | assemblyImportType.FullName, 70 | true, 71 | BindingFlags.CreateInstance, 72 | null, 73 | new object[] { currentDomain.BaseDirectory }, 74 | null, 75 | new object[0]); 76 | 77 | return hostAppDomain; 78 | } 79 | 80 | protected override IManagedAppBase CreateAndStartServerInstance() 81 | { 82 | IManagedApp appServer; 83 | 84 | try 85 | { 86 | m_HostDomain = CreateHostAppDomain(); 87 | 88 | m_HostDomain.SetData(typeof(IsolationMode).Name, IsolationMode.AppDomain); 89 | 90 | var marshalServerType = typeof(MarshalManagedApp); 91 | 92 | appServer = (IManagedApp)m_HostDomain.CreateInstanceAndUnwrap(marshalServerType.Assembly.FullName, 93 | marshalServerType.FullName, 94 | true, 95 | BindingFlags.CreateInstance, 96 | null, 97 | new object[] { GetMetadata().AppType }, 98 | null, 99 | new object[0]); 100 | 101 | if (!appServer.Setup(Bootstrap, Config)) 102 | { 103 | OnExceptionThrown(new Exception("Failed to setup MarshalManagedApp")); 104 | return null; 105 | } 106 | 107 | if (!appServer.Start()) 108 | { 109 | OnExceptionThrown(new Exception("Failed to start MarshalManagedApp")); 110 | return null; 111 | } 112 | 113 | m_HostDomain.DomainUnload += new EventHandler(m_HostDomain_DomainUnload); 114 | 115 | return appServer; 116 | } 117 | catch (Exception e) 118 | { 119 | if (m_HostDomain != null) 120 | { 121 | AppDomain.Unload(m_HostDomain); 122 | m_HostDomain = null; 123 | } 124 | 125 | OnExceptionThrown(e); 126 | return null; 127 | } 128 | } 129 | 130 | protected override void Stop() 131 | { 132 | if (m_HostDomain != null) 133 | { 134 | AppDomain.Unload(m_HostDomain); 135 | } 136 | } 137 | 138 | 139 | void m_HostDomain_DomainUnload(object sender, EventArgs e) 140 | { 141 | m_HostDomain = null; 142 | OnStopped(); 143 | } 144 | 145 | protected override StatusInfoCollection CollectStatus() 146 | { 147 | var app = ManagedApp; 148 | 149 | if (app == null) 150 | return null; 151 | 152 | var status = app.CollectStatus(); 153 | 154 | if(m_AppDomainMonitoringSupported) 155 | { 156 | status[StatusInfoKeys.MemoryUsage] = m_HostDomain == null ? 0 : m_HostDomain.MonitoringSurvivedMemorySize; 157 | 158 | var process = Process.GetCurrentProcess(); 159 | var value = m_HostDomain.MonitoringTotalProcessorTime.TotalMilliseconds * 100 / process.TotalProcessorTime.TotalMilliseconds; 160 | status[StatusInfoKeys.CpuUsage] = value; 161 | } 162 | 163 | return status; 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/AppDomainIsolation/AppDomainBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Configuration; 6 | using NRack.Base; 7 | using NRack.Base.Config; 8 | using NRack.Base.Configuration; 9 | using NRack.Base.Metadata; 10 | using NRack.Server.Isolation; 11 | 12 | namespace NRack.Server.Isolation.AppDomainIsolation 13 | { 14 | class AppDomainBootstrap : IsolationBootstrap 15 | { 16 | public AppDomainBootstrap(IConfigSource configSource) 17 | : base(configSource) 18 | { 19 | 20 | } 21 | 22 | protected override IManagedApp CreateAppInstanceByMetadata(AppServerMetadata metadata) 23 | { 24 | return new AppDomainApp(metadata, ConfigFilePath); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/AssemblyImport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace NRack.Server.Isolation 9 | { 10 | /// 11 | /// AssemblyImport, used for importing assembly to the current AppDomain 12 | /// 13 | public class AssemblyImport : MarshalByRefObject 14 | { 15 | private string m_ImportRoot; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | public AssemblyImport(string importRoot) 21 | { 22 | m_ImportRoot = importRoot; 23 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 24 | } 25 | 26 | //Process cannot resolved assemblies 27 | Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 28 | { 29 | AssemblyName name = new AssemblyName(args.Name); 30 | 31 | var assemblyFilePath = Path.Combine(m_ImportRoot, name.Name + ".dll"); 32 | 33 | if(File.Exists(assemblyFilePath)) 34 | return Assembly.LoadFrom(assemblyFilePath); 35 | 36 | assemblyFilePath = Path.Combine(m_ImportRoot, name.Name + ".exe"); 37 | 38 | if (File.Exists(assemblyFilePath)) 39 | return Assembly.LoadFrom(assemblyFilePath); 40 | 41 | assemblyFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name.Name + ".dll"); 42 | 43 | if (File.Exists(assemblyFilePath)) 44 | return Assembly.LoadFrom(assemblyFilePath); 45 | 46 | assemblyFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, name.Name + ".exe"); 47 | 48 | if (File.Exists(assemblyFilePath)) 49 | return Assembly.LoadFrom(assemblyFilePath); 50 | 51 | return null; 52 | } 53 | 54 | /// 55 | /// Registers the assembply import. 56 | /// 57 | /// The host application domain. 58 | public static void RegisterAssembplyImport(AppDomain hostAppDomain) 59 | { 60 | var assemblyImportType = typeof(AssemblyImport); 61 | 62 | hostAppDomain.CreateInstanceFrom(assemblyImportType.Assembly.CodeBase, 63 | assemblyImportType.FullName, 64 | true, 65 | BindingFlags.CreateInstance, 66 | null, 67 | new object[] { AppDomain.CurrentDomain.BaseDirectory }, 68 | null, 69 | new object[0]); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/IsolationBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | using NRack.Base; 7 | using NRack.Base.Config; 8 | using NRack.Base.Configuration; 9 | using NRack.Base.Metadata; 10 | using NRack.Base.Provider; 11 | using NRack.Server.Config; 12 | using NRack.Server.Recycle; 13 | 14 | namespace NRack.Server.Isolation 15 | { 16 | [StatusInfo(StatusInfoKeys.CpuUsage, Name = "CPU Usage", Format = "{0:0.00}%", DataType = typeof(double), Order = 112)] 17 | [StatusInfo(StatusInfoKeys.MemoryUsage, Name = "Physical Memory Usage", Format = "{0:N}", DataType = typeof(double), Order = 113)] 18 | [StatusInfo(StatusInfoKeys.TotalThreadCount, Name = "Total Thread Count", Format = "{0}", DataType = typeof(double), Order = 114)] 19 | abstract class IsolationBootstrap : BootstrapBase 20 | { 21 | 22 | private IBootstrap m_RemoteBootstrapWrap; 23 | 24 | private IEnumerable> m_RecycleTriggers; 25 | 26 | public IsolationBootstrap(IConfigSource configSource) 27 | : base(GetSerializableConfigSource(configSource)) // make the configuration source serializable 28 | { 29 | HandleConfigSource(configSource); 30 | m_RemoteBootstrapWrap = new RemoteBootstrapProxy(this); 31 | m_RecycleTriggers = AppDomain.CurrentDomain.GetCurrentAppDomainExportProvider().GetExports(); 32 | } 33 | 34 | 35 | private static IConfigSource GetSerializableConfigSource(IConfigSource configSource) 36 | { 37 | if (configSource.GetType().IsSerializable) 38 | { 39 | return configSource; 40 | } 41 | 42 | return new NRackConfig(configSource); 43 | } 44 | 45 | protected override AppServerMetadata GetAppServerMetadata(IServerConfig serverConfig) 46 | { 47 | AppDomain validateDomain = null; 48 | AppServerMetadata metadata = null; 49 | 50 | try 51 | { 52 | validateDomain = AppDomain.CreateDomain("ValidationDomain", AppDomain.CurrentDomain.Evidence, IsolationApp.GetAppWorkingDir(serverConfig), string.Empty, false); 53 | 54 | AssemblyImport.RegisterAssembplyImport(validateDomain); 55 | 56 | validateDomain.SetData(typeof(IsolationMode).Name, ConfigSource.Isolation); 57 | 58 | var validatorType = typeof(RemoteAppTypeValidator); 59 | var validator = (RemoteAppTypeValidator)validateDomain.CreateInstanceAndUnwrap(validatorType.Assembly.FullName, validatorType.FullName); 60 | 61 | var result = validator.GetServerMetadata(serverConfig.Type); 62 | 63 | if(!result.Result) 64 | { 65 | Logger.Error(result.Message); 66 | return null; 67 | } 68 | 69 | metadata = result.Value; 70 | } 71 | finally 72 | { 73 | if (validateDomain != null) 74 | AppDomain.Unload(validateDomain); 75 | } 76 | 77 | return metadata; 78 | } 79 | 80 | void SetupRecycleTriggers(IManagedApp managedApp, IServerConfig config) 81 | { 82 | try 83 | { 84 | var recycleTriggers = config.OptionElements.GetChildConfig("recycleTriggers"); 85 | 86 | if (recycleTriggers == null || !recycleTriggers.Any()) 87 | return; 88 | 89 | var triggers = new List(); 90 | 91 | foreach (var triggerConfig in recycleTriggers) 92 | { 93 | var triggerType = m_RecycleTriggers.FirstOrDefault(t => 94 | t.Metadata.Name.Equals(triggerConfig.Name, StringComparison.OrdinalIgnoreCase)); 95 | 96 | if (triggerType == null) 97 | { 98 | Logger.ErrorFormat("We cannot find a RecycleTrigger with the name '{0}'.", triggerConfig.Name); 99 | continue; 100 | } 101 | 102 | var trigger = triggerType.Value; 103 | 104 | if (!trigger.Initialize(triggerConfig.Options)) 105 | { 106 | Logger.ErrorFormat("Failed to initialize the RecycleTrigger '{0}'.", triggerConfig.Name); 107 | continue; 108 | } 109 | 110 | triggers.Add(trigger); 111 | } 112 | 113 | if (triggers.Any()) 114 | { 115 | (managedApp as IsolationApp).RecycleTriggers = triggers.ToArray(); 116 | } 117 | } 118 | catch (Exception e) 119 | { 120 | Logger.Error("Failed to load recycle triggers.", e); 121 | } 122 | } 123 | 124 | protected override bool Setup(IManagedApp managedApp, IServerConfig config) 125 | { 126 | var ret = managedApp.Setup(m_RemoteBootstrapWrap, config); 127 | 128 | if (!ret) 129 | return false; 130 | 131 | SetupRecycleTriggers(managedApp, config); 132 | return ret; 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/MarshalManagedApp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NRack.Base; 6 | using NRack.Base.Config; 7 | using NRack.Base.Metadata; 8 | 9 | namespace NRack.Server.Isolation 10 | { 11 | /// 12 | /// Marshal wrap for managed app instance 13 | /// We don't want to make the real app instance marshalable 14 | /// 15 | class MarshalManagedApp : MarshalByRefObject, IManagedApp 16 | { 17 | private IManagedApp m_ManagedApp; 18 | 19 | public MarshalManagedApp(string appTypeName) 20 | { 21 | var appType = Type.GetType(appTypeName); 22 | m_ManagedApp = (IManagedApp)Activator.CreateInstance(appType); 23 | } 24 | 25 | public string Name 26 | { 27 | get { return m_ManagedApp.Name; } 28 | } 29 | 30 | public bool Setup(IBootstrap bootstrap, IServerConfig config) 31 | { 32 | return m_ManagedApp.Setup(bootstrap, config); 33 | } 34 | 35 | public ServerState State 36 | { 37 | get { return m_ManagedApp.State; } 38 | } 39 | 40 | public IServerConfig Config 41 | { 42 | get { return m_ManagedApp.Config; } 43 | } 44 | 45 | public AppServerMetadata GetMetadata() 46 | { 47 | return m_ManagedApp.GetMetadata(); 48 | } 49 | 50 | public bool Start() 51 | { 52 | return m_ManagedApp.Start(); 53 | } 54 | 55 | public void Stop() 56 | { 57 | m_ManagedApp.Stop(); 58 | } 59 | 60 | public bool CanBeRecycled() 61 | { 62 | return m_ManagedApp.CanBeRecycled(); 63 | } 64 | 65 | public StatusInfoCollection CollectStatus() 66 | { 67 | return m_ManagedApp.CollectStatus(); 68 | } 69 | 70 | public void ReportPotentialConfigChange(IServerConfig config) 71 | { 72 | m_ManagedApp.ReportPotentialConfigChange(config); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/ProcessIsolation/ExternalProcessAppServerMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NRack.Base; 7 | 8 | namespace NRack.Server.Isolation.ProcessIsolation 9 | { 10 | class ExternalProcessAppServerMetadata : AppServerMetadata 11 | { 12 | public ExternalProcessAppServerMetadata(string appDir, string appFile, string appArgs) 13 | { 14 | AppDir = appDir; 15 | AppFile = appFile; 16 | AppArgs = appArgs; 17 | } 18 | 19 | public string AppDir { get; private set; } 20 | 21 | public string AppFile { get; private set; } 22 | 23 | public string AppArgs { get; private set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/ProcessIsolation/ProcessBootstrap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NRack.Base; 6 | using NRack.Base.Config; 7 | using NRack.Base.Metadata; 8 | using NRack.Server.Isolation; 9 | 10 | namespace NRack.Server.Isolation.ProcessIsolation 11 | { 12 | class ProcessBootstrap : IsolationBootstrap 13 | { 14 | public ProcessBootstrap(IConfigSource configSource) 15 | : base(configSource) 16 | { 17 | 18 | } 19 | 20 | protected override IManagedApp CreateAppInstance(IServerConfig serverConfig) 21 | { 22 | var appFile = serverConfig.Options.Get("appFile"); 23 | 24 | if(string.IsNullOrEmpty(appFile)) 25 | return base.CreateAppInstance(serverConfig); 26 | 27 | var serverMetadata = new ExternalProcessAppServerMetadata(serverConfig.Options.Get("appDir"), appFile, serverConfig.Options.Get("appArgs")); 28 | return new ExternalProcessApp(serverMetadata, ConfigFilePath); 29 | } 30 | 31 | protected override IManagedApp CreateAppInstanceByMetadata(AppServerMetadata metadata) 32 | { 33 | return new ProcessApp(metadata, ConfigFilePath); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NRack.Server/Isolation/ProcessIsolation/ProcessLocker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using Microsoft.Win32.SafeHandles; 9 | using NRack.Base; 10 | 11 | namespace NRack.Server 12 | { 13 | class ProcessLocker 14 | { 15 | private string m_LockFilePath; 16 | 17 | public ProcessLocker(string workDir, string lockFileName) 18 | { 19 | m_LockFilePath = Path.Combine(workDir, lockFileName); 20 | } 21 | 22 | public Process GetLockedProcess() 23 | { 24 | if (!File.Exists(m_LockFilePath)) 25 | return null; 26 | 27 | int processId; 28 | 29 | var lockFileText = File.ReadAllText(m_LockFilePath); 30 | 31 | var lockFileInfoArray = lockFileText.Split(','); 32 | 33 | if (!int.TryParse(lockFileInfoArray[0], out processId)) 34 | { 35 | File.Delete(m_LockFilePath); 36 | return null; 37 | } 38 | 39 | try 40 | { 41 | var process = Process.GetProcessById(processId); 42 | 43 | var safeInputHandle = new SafeFileHandle(new IntPtr(long.Parse(lockFileInfoArray[1])), true); 44 | 45 | var standardInput = new StreamWriter(new FileStream(safeInputHandle, FileAccess.Write, 4096, false), Encoding.UTF8, 4096); 46 | standardInput.AutoFlush = true; 47 | 48 | var standInputFieldName = NRackEnv.IsMono ? "input_stream" : "standardInput"; 49 | 50 | var standInputField = process.GetType().GetField(standInputFieldName, 51 | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField | BindingFlags.GetField); 52 | 53 | standInputField.SetValue(process, standardInput); 54 | 55 | return process; 56 | } 57 | catch 58 | { 59 | File.Delete(m_LockFilePath); 60 | return null; 61 | } 62 | } 63 | 64 | public void SaveLock(Process process) 65 | { 66 | var inputHandle = (process.StandardInput.BaseStream as FileStream) 67 | .SafeFileHandle 68 | .DangerousGetHandle().ToInt64(); 69 | 70 | File.WriteAllText(m_LockFilePath, string.Format("{0},{1}", process.Id, inputHandle)); 71 | } 72 | 73 | public void CleanLock() 74 | { 75 | if (File.Exists(m_LockFilePath)) 76 | File.Delete(m_LockFilePath); 77 | } 78 | 79 | ~ProcessLocker() 80 | { 81 | CleanLock(); 82 | } 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/NRack.Server/MefExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Composition; 4 | using System.ComponentModel.Composition.Primitives; 5 | using System.ComponentModel.Composition.ReflectionModel; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | 10 | namespace NRack.Server 11 | { 12 | public static class MefExtensions 13 | { 14 | public static Type GetExportType(this Lazy lazyFactory) 15 | { 16 | var valueFactoryField = typeof(Lazy) 17 | .GetField("m_valueFactory", BindingFlags.Instance | BindingFlags.NonPublic); 18 | 19 | var valueFactory = (Func)valueFactoryField.GetValue(lazyFactory); 20 | 21 | var exportField = valueFactory.Target.GetType() 22 | .GetField("export", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 23 | 24 | var export = exportField.GetValue(valueFactory.Target) as Export; 25 | var memberInfo = (LazyMemberInfo)export.Definition.GetType() 26 | .GetProperty("ExportingLazyMember").GetValue(export.Definition, null); 27 | 28 | return memberInfo.GetAccessors()[0] as Type; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NRack.Server/NRack.Server.Net45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45} 8 | Exe 9 | Properties 10 | NRack.Server 11 | NRack.Server 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\net45\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | false 25 | 26 | 27 | pdbonly 28 | true 29 | bin\net45\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | false 34 | 35 | 36 | 37 | 38 | 39 | 40 | ..\packages\AnyLog.0.1.8\lib\net45\AnyLog.dll 41 | True 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | GlobalAssemblyInfo.cs 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Code 84 | 85 | 86 | 87 | 88 | Component 89 | 90 | 91 | NRackService.cs 92 | 93 | 94 | Component 95 | 96 | 97 | NRackServiceInstaller.cs 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 107 | NRack.Base.Net45 108 | 109 | 110 | 111 | 112 | 113 | PreserveNewest 114 | 115 | 116 | PreserveNewest 117 | 118 | 119 | PreserveNewest 120 | 121 | 122 | PreserveNewest 123 | 124 | 125 | 126 | 127 | 128 | 135 | -------------------------------------------------------------------------------- /src/NRack.Server/NRack.Server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45} 8 | Exe 9 | Properties 10 | NRack.Server 11 | NRack.Server 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\net40\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\net40\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | ..\packages\AnyLog.0.1.8\lib\net40\AnyLog.dll 39 | True 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | GlobalAssemblyInfo.cs 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Code 85 | 86 | 87 | 88 | 89 | Component 90 | 91 | 92 | NRackService.cs 93 | 94 | 95 | Component 96 | 97 | 98 | NRackServiceInstaller.cs 99 | 100 | 101 | 102 | 103 | 104 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 105 | NRack.Base 106 | 107 | 108 | 109 | 110 | 111 | PreserveNewest 112 | 113 | 114 | PreserveNewest 115 | 116 | 117 | PreserveNewest 118 | 119 | 120 | PreserveNewest 121 | 122 | 123 | 124 | 125 | 126 | 133 | -------------------------------------------------------------------------------- /src/NRack.Server/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("NRack.Server")] 9 | [assembly: AssemblyDescription("NRack.Server")] 10 | [assembly: AssemblyConfiguration("")] 11 | // Setting ComVisible to false makes the types in this assembly not visible 12 | // to COM components. If you need to access a type in this assembly from 13 | // COM, set the ComVisible attribute to true on that type. 14 | [assembly: ComVisible(false)] 15 | 16 | // The following GUID is for the ID of the typelib if this project is exposed to COM 17 | [assembly: Guid("89c20989-7759-40db-abbb-217e7229808c")] 18 | -------------------------------------------------------------------------------- /src/NRack.Server/Recycle/AssemblyUpdatedRecycleTrigger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.ComponentModel.Composition; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using NRack.Base; 10 | using NRack.Base.Configuration; 11 | using NRack.Base.Provider; 12 | using NRack.Server.Isolation; 13 | 14 | namespace NRack.Server.Recycle 15 | { 16 | [Export(typeof(IRecycleTrigger))] 17 | [ProviderMetadata(TriggerName)] 18 | public class AssemblyUpdatedRecycleTrigger : IRecycleTrigger 19 | { 20 | private int m_CheckInterval; 21 | private int m_RestartRelay; 22 | 23 | internal const string TriggerName = "AssemblyUpdatedTrigger"; 24 | 25 | public string Name 26 | { 27 | get 28 | { 29 | return TriggerName; 30 | } 31 | } 32 | 33 | public bool Initialize(NameValueCollection options) 34 | { 35 | var checkInterval = 0; 36 | 37 | if (!int.TryParse(options.GetValue("checkInterval", "5"), out checkInterval)) 38 | return false; 39 | 40 | m_CheckInterval = checkInterval; 41 | 42 | var restartDelay = 0; 43 | 44 | if (!int.TryParse(options.GetValue("restartDelay", "1"), out restartDelay)) 45 | return false; 46 | 47 | m_RestartRelay = restartDelay; 48 | 49 | return true; 50 | } 51 | 52 | private bool IsDeplayOverdue(DateTime lastUpdatedTime) 53 | { 54 | if (lastUpdatedTime.AddMinutes(m_RestartRelay) <= DateTime.Now) 55 | return true; 56 | 57 | return false; 58 | } 59 | 60 | public bool NeedBeRecycled(IManagedApp app, StatusInfoCollection status) 61 | { 62 | var state = (app as IsolationApp).AssemblyUpdateState; 63 | 64 | // not in running state 65 | if (state == null) 66 | return false; 67 | 68 | if (state.LastUpdatedTime > state.CurrentAssemblyTime) 69 | { 70 | // check to see if there is any latest update 71 | // if yes, deplay much longer time 72 | state.TryCheckUpdate(); 73 | return IsDeplayOverdue(state.LastUpdatedTime); 74 | } 75 | 76 | // next check time has not reached yet 77 | if (state.LastCheckTime.AddMinutes(m_CheckInterval) > DateTime.Now) 78 | return false; 79 | 80 | if (!state.TryCheckUpdate()) 81 | return false; 82 | 83 | return IsDeplayOverdue(state.LastUpdatedTime); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/NRack.Server/Recycle/IRecycleTrigger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NRack.Base; 8 | 9 | namespace NRack.Server.Recycle 10 | { 11 | public interface IRecycleTrigger 12 | { 13 | string Name { get; } 14 | 15 | bool Initialize(NameValueCollection options); 16 | 17 | bool NeedBeRecycled(IManagedApp app, StatusInfoCollection status); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NRack.Server/Recycle/MemoryRecycleTrigger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.Specialized; 4 | using System.ComponentModel.Composition; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using NRack.Base; 9 | using NRack.Base.Configuration; 10 | using NRack.Base.Metadata; 11 | using NRack.Base.Provider; 12 | 13 | namespace NRack.Server.Recycle 14 | { 15 | [Export(typeof(IRecycleTrigger))] 16 | [ProviderMetadata(TriggerName)] 17 | public class MemoryRecycleTrigger : IRecycleTrigger 18 | { 19 | private long m_MaxMemoryUsage; 20 | 21 | internal const string TriggerName = "MemoryTrigger"; 22 | 23 | public string Name 24 | { 25 | get 26 | { 27 | return TriggerName; 28 | } 29 | } 30 | 31 | public bool Initialize(NameValueCollection options) 32 | { 33 | if (long.TryParse(options.GetValue("maxMemoryUsage"), out m_MaxMemoryUsage) || m_MaxMemoryUsage <= 0) 34 | return false; 35 | 36 | return true; 37 | } 38 | 39 | public bool NeedBeRecycled(IManagedApp app, StatusInfoCollection status) 40 | { 41 | var memoryUsage = status[StatusInfoKeys.MemoryUsage]; 42 | 43 | if (memoryUsage == null) 44 | return false; 45 | 46 | return (long)memoryUsage >= m_MaxMemoryUsage; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NRack.Server/Recycle/RecycleTriggerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NRack.Base.Config; 8 | 9 | namespace NRack.Server.Config 10 | { 11 | public class RecycleTriggerConfig : ConfigurationElementBase 12 | { 13 | public RecycleTriggerConfig() 14 | : base(true) 15 | { 16 | 17 | } 18 | 19 | [ConfigurationProperty("type", IsRequired = false)] 20 | public string Type 21 | { 22 | get { return this["type"] as string; } 23 | } 24 | } 25 | 26 | [ConfigurationCollection(typeof(RecycleTriggerConfig), AddItemName = "trigger")] 27 | class RecycleTriggerConfigCollection : GenericConfigurationElementCollectionBase 28 | { 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NRack.Server/RemoteAppGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using NRack.Base; 6 | using NRack.Base.Config; 7 | using NRack.Base.Metadata; 8 | 9 | namespace NRack.Server 10 | { 11 | class ManagedAppGroup : IManagedApp 12 | { 13 | public string Name { get; private set; } 14 | 15 | public IManagedApp[] Items { get; private set; } 16 | 17 | public ManagedAppGroup(string name, IEnumerable groupItems) 18 | { 19 | if (string.IsNullOrEmpty(name)) 20 | throw new ArgumentNullException("name"); 21 | 22 | if (groupItems == null || !groupItems.Any()) 23 | throw new ArgumentNullException("name"); 24 | 25 | Name = name; 26 | Items = groupItems.ToArray(); 27 | } 28 | 29 | public bool Setup(IBootstrap bootstrap, IServerConfig config) 30 | { 31 | Config = config; 32 | 33 | foreach (var item in Items) 34 | { 35 | if (!item.Setup(bootstrap, config)) 36 | return false; 37 | } 38 | 39 | return true; 40 | } 41 | 42 | public bool Start() 43 | { 44 | foreach (var item in Items) 45 | { 46 | if (!item.Start()) 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | 53 | public void Stop() 54 | { 55 | foreach (var item in Items) 56 | { 57 | item.Stop(); 58 | } 59 | } 60 | 61 | 62 | public IServerConfig Config { get; private set; } 63 | 64 | public AppServerMetadata GetMetadata() 65 | { 66 | throw new NotImplementedException(); 67 | } 68 | 69 | 70 | public ServerState State { get; private set; } 71 | 72 | 73 | public bool CanBeRecycled() 74 | { 75 | return true; 76 | } 77 | 78 | public StatusInfoCollection CollectStatus() 79 | { 80 | throw new NotImplementedException(); 81 | } 82 | 83 | public void ReportPotentialConfigChange(IServerConfig config) 84 | { 85 | foreach (var item in Items) 86 | { 87 | item.ReportPotentialConfigChange(config); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/NRack.Server/RemoteAppTypeValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Composition.Hosting; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using NRack.Base; 8 | using NRack.Base.Metadata; 9 | 10 | namespace NRack.Server 11 | { 12 | [Serializable] 13 | public class RemoteTypeLoadResult 14 | { 15 | public bool Result { get; set; } 16 | 17 | public T Value { get; set; } 18 | 19 | public string Message { get; set; } 20 | } 21 | 22 | public class RemoteAppTypeValidator : MarshalByRefObject 23 | { 24 | private CompositionContainer m_ExportProvider; 25 | 26 | public RemoteAppTypeValidator() 27 | { 28 | m_ExportProvider = AppDomain.CurrentDomain.GetCurrentAppDomainExportProvider(); 29 | } 30 | 31 | public RemoteTypeLoadResult GetServerMetadata(string serverTypeName) 32 | { 33 | Lazy lazyServerFactory = null; 34 | 35 | try 36 | { 37 | lazyServerFactory = m_ExportProvider.GetExports() 38 | .FirstOrDefault(f => f.Metadata.Name.Equals(serverTypeName, StringComparison.OrdinalIgnoreCase)); 39 | } 40 | catch (ReflectionTypeLoadException e) 41 | { 42 | var msg = e.Message; 43 | 44 | foreach (var le in e.LoaderExceptions) 45 | { 46 | msg += Environment.NewLine + le.Message; 47 | } 48 | 49 | return new RemoteTypeLoadResult { Message = msg }; 50 | } 51 | 52 | AppServerMetadata metadata = null; 53 | 54 | try 55 | { 56 | if (lazyServerFactory != null) 57 | { 58 | metadata = new AppServerMetadata(lazyServerFactory.Metadata, lazyServerFactory.GetExportType()); 59 | } 60 | else 61 | { 62 | metadata = AppServerMetadata.GetAppServerMetadata(Type.GetType(serverTypeName, true, true)); 63 | } 64 | } 65 | catch(Exception e) 66 | { 67 | return new RemoteTypeLoadResult { Message = e.Message + Environment.NewLine + e.StackTrace }; 68 | } 69 | 70 | return new RemoteTypeLoadResult { Result = true, Value = metadata }; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/NRack.Server/RemoteBootstrapProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using AnyLog; 6 | using NRack.Base; 7 | using NRack.Base.Config; 8 | 9 | namespace NRack.Server 10 | { 11 | class RemoteBootstrapProxy : MarshalByRefObject, IBootstrap, ILoggerProvider 12 | { 13 | class ServerProxy : MarshalByRefObject, IManagedApp 14 | { 15 | private IManagedApp m_ManagedApp; 16 | 17 | public ServerProxy(IManagedApp app) 18 | { 19 | m_ManagedApp = app; 20 | } 21 | 22 | public ServerState State 23 | { 24 | get { return m_ManagedApp.State; } 25 | } 26 | 27 | public string Name 28 | { 29 | get { return m_ManagedApp.Name; } 30 | } 31 | public bool Start() 32 | { 33 | return m_ManagedApp.Start(); 34 | } 35 | 36 | public void Stop() 37 | { 38 | m_ManagedApp.Stop(); 39 | } 40 | 41 | public bool Setup(IBootstrap bootstrap, IServerConfig config) 42 | { 43 | throw new NotImplementedException(); 44 | } 45 | 46 | public IServerConfig Config 47 | { 48 | get { return m_ManagedApp.Config; } 49 | } 50 | 51 | public AppServerMetadata GetMetadata() 52 | { 53 | return m_ManagedApp.GetMetadata(); 54 | } 55 | 56 | public bool CanBeRecycled() 57 | { 58 | return m_ManagedApp.CanBeRecycled(); 59 | } 60 | 61 | public StatusInfoCollection CollectStatus() 62 | { 63 | return m_ManagedApp.CollectStatus(); 64 | } 65 | 66 | public void ReportPotentialConfigChange(IServerConfig config) 67 | { 68 | m_ManagedApp.ReportPotentialConfigChange(config); 69 | } 70 | 71 | public override object InitializeLifetimeService() 72 | { 73 | //Never expire 74 | return null; 75 | } 76 | } 77 | 78 | private IBootstrap m_Bootstrap; 79 | 80 | private List m_ManagedApps; 81 | 82 | public RemoteBootstrapProxy(IBootstrap innerBootstrap) 83 | { 84 | m_Bootstrap = innerBootstrap; 85 | m_ManagedApps = new List(); 86 | 87 | foreach (var s in m_Bootstrap.AppServers) 88 | { 89 | if (s is MarshalByRefObject) 90 | m_ManagedApps.Add(s); 91 | else 92 | m_ManagedApps.Add(new ServerProxy(s)); 93 | } 94 | } 95 | 96 | public RemoteBootstrapProxy() 97 | : this(AppDomain.CurrentDomain.GetBootstrap()) 98 | { 99 | 100 | } 101 | 102 | public IEnumerable AppServers 103 | { 104 | get 105 | { 106 | return m_ManagedApps; 107 | } 108 | } 109 | 110 | ILog ILoggerProvider.Logger 111 | { 112 | get 113 | { 114 | var loggerProvider = m_Bootstrap as ILoggerProvider; 115 | 116 | if (loggerProvider == null) 117 | return null; 118 | 119 | return loggerProvider.Logger; 120 | } 121 | } 122 | 123 | public string ConfigFilePath 124 | { 125 | get 126 | { 127 | return m_Bootstrap.ConfigFilePath; 128 | } 129 | } 130 | 131 | public bool Initialize() 132 | { 133 | throw new NotSupportedException(); 134 | } 135 | 136 | public void Start() 137 | { 138 | throw new NotSupportedException(); 139 | } 140 | 141 | public void Stop() 142 | { 143 | throw new NotSupportedException(); 144 | } 145 | 146 | public override object InitializeLifetimeService() 147 | { 148 | //Never expire 149 | return null; 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/NRack.Server/Service/NRackService.Designer.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace NRack.Server.Service 4 | { 5 | partial class NRackService 6 | { 7 | /// 8 | /// Required designer variable. 9 | /// 10 | private System.ComponentModel.IContainer components = null; 11 | 12 | /// 13 | /// Clean up any resources being used. 14 | /// 15 | /// true if managed resources should be disposed; otherwise, false. 16 | protected override void Dispose(bool disposing) 17 | { 18 | if (disposing && (components != null)) 19 | { 20 | components.Dispose(); 21 | } 22 | base.Dispose(disposing); 23 | } 24 | 25 | #region Component Designer generated code 26 | 27 | /// 28 | /// Required method for Designer support - do not modify 29 | /// the contents of this method with the code editor. 30 | /// 31 | private void InitializeComponent() 32 | { 33 | components = new System.ComponentModel.Container(); 34 | } 35 | 36 | #endregion 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NRack.Server/Service/NRackService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Configuration; 5 | using System.Diagnostics; 6 | using System.ServiceProcess; 7 | using System.Text; 8 | using NRack.Base; 9 | 10 | namespace NRack.Server.Service 11 | { 12 | partial class NRackService : ServiceBase 13 | { 14 | private IBootstrap m_Bootstrap; 15 | 16 | public NRackService() 17 | { 18 | InitializeComponent(); 19 | ServiceName = ConfigurationManager.AppSettings["ServiceName"]; 20 | m_Bootstrap = BootstrapFactory.CreateBootstrap(); 21 | } 22 | 23 | protected override void OnStart(string[] args) 24 | { 25 | if (!m_Bootstrap.Initialize()) 26 | return; 27 | 28 | m_Bootstrap.Start(); 29 | } 30 | 31 | protected override void OnStop() 32 | { 33 | m_Bootstrap.Stop(); 34 | base.OnStop(); 35 | } 36 | 37 | protected override void OnShutdown() 38 | { 39 | m_Bootstrap.Stop(); 40 | base.OnShutdown(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/NRack.Server/Service/NRackServiceInstaller.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace NRack.Server.Service 2 | { 3 | partial class NRackServiceInstaller 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | } 33 | 34 | #endregion 35 | } 36 | } -------------------------------------------------------------------------------- /src/NRack.Server/Service/NRackServiceInstaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Configuration; 5 | using System.Configuration.Install; 6 | using System.ServiceProcess; 7 | 8 | namespace NRack.Server.Service 9 | { 10 | [RunInstaller(true)] 11 | public partial class NRackServiceInstaller : Installer 12 | { 13 | private ServiceInstaller serviceInstaller; 14 | private ServiceProcessInstaller processInstaller; 15 | 16 | public NRackServiceInstaller() 17 | { 18 | InitializeComponent(); 19 | 20 | processInstaller = new ServiceProcessInstaller(); 21 | serviceInstaller = new ServiceInstaller(); 22 | 23 | processInstaller.Account = ServiceAccount.LocalSystem; 24 | serviceInstaller.StartType = ServiceStartMode.Automatic; 25 | serviceInstaller.ServiceName = ConfigurationManager.AppSettings["ServiceName"]; 26 | 27 | var serviceDescription = ConfigurationManager.AppSettings["ServiceDescription"]; 28 | if (!string.IsNullOrEmpty(serviceDescription)) 29 | serviceInstaller.Description = serviceDescription; 30 | 31 | var servicesDependedOn = new List { "tcpip" }; 32 | var servicesDependedOnConfig = ConfigurationManager.AppSettings["ServicesDependedOn"]; 33 | 34 | if (!string.IsNullOrEmpty(servicesDependedOnConfig)) 35 | servicesDependedOn.AddRange(servicesDependedOnConfig.Split(new char[] { ',', ';' })); 36 | 37 | serviceInstaller.ServicesDependedOn = servicesDependedOn.ToArray(); 38 | 39 | Installers.Add(serviceInstaller); 40 | Installers.Add(processInstaller); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/NRack.Server/Service/SelfInstaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration.Install; 3 | using System.Reflection; 4 | 5 | namespace NRack.Server.Service 6 | { 7 | public static class SelfInstaller 8 | { 9 | private static readonly string _exePath = Assembly.GetEntryAssembly().Location; 10 | 11 | public static bool InstallMe() 12 | { 13 | try 14 | { 15 | ManagedInstallerClass.InstallHelper(new string[] { _exePath }); 16 | } 17 | catch 18 | { 19 | return false; 20 | } 21 | return true; 22 | } 23 | 24 | public static bool UninstallMe() 25 | { 26 | try 27 | { 28 | ManagedInstallerClass.InstallHelper(new string[] { "/u", _exePath }); 29 | } 30 | catch 31 | { 32 | return false; 33 | } 34 | 35 | return true; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NRack.Server/Utils/PerformanceCounterInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NRack.Base.Metadata; 7 | 8 | namespace NRack.Server.Utils 9 | { 10 | public class PerformanceCounterInfo 11 | { 12 | /// 13 | /// Gets or sets the performance counter category. 14 | /// 15 | /// 16 | /// The category. 17 | /// 18 | public string Category { get; set; } 19 | 20 | /// 21 | /// Gets or sets the performance counter name. 22 | /// 23 | /// 24 | /// The name. 25 | /// 26 | public string Name { get; set; } 27 | 28 | 29 | /// 30 | /// Gets or sets the status information key. 31 | /// 32 | /// 33 | /// The status information key. 34 | /// 35 | public string StatusInfoKey { get; set; } 36 | 37 | /// 38 | /// Gets or sets the performacne counter data reader. 39 | /// 40 | /// 41 | /// The reader. 42 | /// 43 | public Func Read { get; set; } 44 | 45 | 46 | internal static PerformanceCounterInfo[] GetDefaultPerformanceCounterDefinitions() 47 | { 48 | return new PerformanceCounterInfo[] 49 | { 50 | new PerformanceCounterInfo 51 | { 52 | Category = "Process", 53 | Name = "% Processor Time", 54 | StatusInfoKey = StatusInfoKeys.CpuUsage, 55 | Read = (value) => value / Environment.ProcessorCount 56 | }, 57 | new PerformanceCounterInfo 58 | { 59 | Category = "Process", 60 | Name = "Thread Count", 61 | StatusInfoKey = StatusInfoKeys.TotalThreadCount, 62 | Read = (value) => (int)value 63 | }, 64 | new PerformanceCounterInfo 65 | { 66 | Category = "Process", 67 | Name = "Working Set", 68 | StatusInfoKey = StatusInfoKeys.MemoryUsage, 69 | Read = (value) => (long)value 70 | } 71 | }; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/NRack.Server/nrack.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | NRack.Server.exe -c %1 %2 3 | -------------------------------------------------------------------------------- /src/NRack.Server/nrack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mono NRack.Server.exe -c $1 $2 3 | -------------------------------------------------------------------------------- /src/NRack.Server/packages.NRack.Server.Net45.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/NRack.Server/packages.NRack.Server.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/NRack.Test/AppDomainIsolationTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NUnit.Framework; 7 | 8 | namespace NRack.Test 9 | { 10 | [TestFixture] 11 | public class AppDomainIsolationTest : Test 12 | { 13 | protected override string ConfigFile 14 | { 15 | get 16 | { 17 | return "AppDomainIsolation.config"; 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NRack.Test/Asserts/Config/AppDomainIsolation.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/NRack.Test/Asserts/Config/Basic.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/NRack.Test/Asserts/Config/ProcessIsolation.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/NRack.Test/NRack.Test.Net45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F} 7 | Library 8 | NRack.Test 9 | NRack.Test 10 | v4.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | bin\Release 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | 32 | ..\packages\AnyLog.0.1.8\lib\net45\AnyLog.dll 33 | True 34 | 35 | 36 | 37 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | PreserveNewest 52 | 53 | 54 | PreserveNewest 55 | 56 | 57 | 58 | PreserveNewest 59 | 60 | 61 | 62 | 63 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 64 | NDock.Base.Net45 65 | 66 | 67 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45} 68 | NDock.Server.Net45 69 | 70 | 71 | {93a2e31d-9af3-4c9e-986c-1659309f5436} 72 | NDock.Worker.Net45 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/NRack.Test/NRack.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F} 7 | Library 8 | NRack.Test 9 | NRack.Test 10 | v4.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | false 21 | 22 | 23 | full 24 | true 25 | bin\Release 26 | prompt 27 | 4 28 | false 29 | 30 | 31 | 32 | ..\packages\AnyLog.0.1.8\lib\net45\AnyLog.dll 33 | True 34 | 35 | 36 | 37 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | PreserveNewest 52 | 53 | 54 | PreserveNewest 55 | 56 | 57 | 58 | PreserveNewest 59 | 60 | 61 | 62 | 63 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 64 | NRack.Base 65 | 66 | 67 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45} 68 | NRack.Server 69 | 70 | 71 | {93a2e31d-9af3-4c9e-986c-1659309f5436} 72 | NRack.Worker 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/NRack.Test/ProcessIsolationTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NUnit.Framework; 8 | 9 | namespace NRack.Test 10 | { 11 | [TestFixture] 12 | public class ProcessIsolationTest : Test 13 | { 14 | protected override string ConfigFile 15 | { 16 | get 17 | { 18 | return "ProcessIsolation.config"; 19 | } 20 | } 21 | 22 | [Test] 23 | public void ConfigurationShareTest() 24 | { 25 | StartStopWrap(() => 26 | { 27 | var NRackTextFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NRack.Test.txt"); 28 | 29 | if (!File.Exists(NRackTextFilePath)) 30 | Assert.Fail(string.Format("The file {0} was not generated.", NRackTextFilePath)); 31 | 32 | Assert.AreEqual("Hello NRack", File.ReadAllText(NRackTextFilePath, Encoding.UTF8)); 33 | 34 | File.Delete(NRackTextFilePath); 35 | }); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/NRack.Test/Test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using NRack.Base; 9 | using NRack.Server; 10 | using NUnit.Framework; 11 | 12 | namespace NRack.Test 13 | { 14 | [TestFixture] 15 | public class Test 16 | { 17 | protected virtual string ConfigFile 18 | { 19 | get { return "Basic.config"; } 20 | } 21 | 22 | private IBootstrap GetBootstrap() 23 | { 24 | var configFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Asserts", "Config", ConfigFile); 25 | return BootstrapFactory.CreateBootstrapFromConfigFile(configFile); 26 | } 27 | 28 | [Test] 29 | public void ConfigLoadTest() 30 | { 31 | var bootstrap = GetBootstrap(); 32 | Assert.IsNotNull(bootstrap); 33 | Assert.IsTrue(bootstrap.Initialize()); 34 | } 35 | 36 | [Test] 37 | public void StartStopTest() 38 | { 39 | StartStopWrap(null); 40 | } 41 | 42 | protected void StartStopWrap(Action action) 43 | { 44 | var bootstrap = GetBootstrap(); 45 | Assert.IsNotNull(bootstrap); 46 | Assert.IsTrue(bootstrap.Initialize()); 47 | 48 | var server = bootstrap.AppServers.FirstOrDefault(); 49 | 50 | Assert.AreEqual(ServerState.NotStarted, server.State); 51 | 52 | bootstrap.Start(); 53 | Assert.AreEqual(ServerState.Running, server.State); 54 | 55 | if(action != null) 56 | action(); 57 | 58 | bootstrap.Stop(); 59 | Assert.AreEqual(ServerState.NotStarted, server.State); 60 | } 61 | 62 | [Test] 63 | public void StatusCollectTest() 64 | { 65 | StartStopWrap(() => 66 | { 67 | //Thread.Sleep(1000 * 60 * 5); 68 | }); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/NRack.Test/TestAppServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NRack.Base; 3 | using NRack.Base.Config; 4 | using NRack.Base.Metadata; 5 | using System.ComponentModel.Composition.Hosting; 6 | using System.Configuration; 7 | using System.IO; 8 | using System.Text; 9 | 10 | namespace NRack.Test 11 | { 12 | [AppServerMetadata("TestAppServer")] 13 | public class TestAppServer : AppServer 14 | { 15 | public override bool Start() 16 | { 17 | var NRackText = ConfigurationManager.AppSettings["NRack.Test"]; 18 | 19 | if(!string.IsNullOrEmpty(NRackText)) 20 | { 21 | var NRackTextFilePath = Path.Combine(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).Parent.FullName, "NRack.Test.txt"); 22 | File.WriteAllText(NRackTextFilePath, NRackText, Encoding.UTF8); 23 | } 24 | 25 | return true; 26 | } 27 | 28 | public override void Stop() 29 | { 30 | 31 | } 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/NRack.Test/packages.NRack.Test.Net45.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/NRack.Test/packages.NRack.Test.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/NRack.Worker/ManagedAppWorker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using AnyLog; 7 | using NRack.Base; 8 | using NRack.Base.Config; 9 | using NRack.Base.Configuration; 10 | using NRack.Base.Metadata; 11 | using NRack.Server; 12 | using NRack.Server.Isolation; 13 | 14 | namespace NRack.Worker 15 | { 16 | /// 17 | /// The service exposed to bootstrap to control the agent 18 | /// 19 | public class ManagedAppWorker : MarshalByRefObject, IRemoteManagedApp 20 | { 21 | private IManagedApp m_AppServer; 22 | 23 | #pragma warning disable 0414 24 | private AssemblyImport m_AssemblyImporter; 25 | #pragma warning restore 0414 26 | 27 | private ILog m_Log; 28 | 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | public ManagedAppWorker() 33 | { 34 | 35 | } 36 | 37 | public bool Setup(string serverType, string bootstrapUri, string assemblyImportRoot, IServerConfig config, string startupConfigFile) 38 | { 39 | m_AssemblyImporter = new AssemblyImport(assemblyImportRoot); 40 | 41 | if(!string.IsNullOrEmpty(startupConfigFile)) 42 | { 43 | AppDomain.CurrentDomain.ResetConfiguration(startupConfigFile); 44 | } 45 | 46 | var serviceType = Type.GetType(serverType); 47 | m_AppServer = (IManagedApp)Activator.CreateInstance(serviceType); 48 | 49 | var bootstrap = (IBootstrap)Activator.GetObject(typeof(IBootstrap), bootstrapUri); 50 | 51 | var ret = m_AppServer.Setup(bootstrap, config); 52 | 53 | if (ret) 54 | { 55 | m_Log = ((IAppServer)m_AppServer).Logger; 56 | AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 57 | } 58 | 59 | return ret; 60 | } 61 | 62 | void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 63 | { 64 | if (m_Log != null) 65 | { 66 | m_Log.Error("The process crashed for an unhandled exception!", (Exception)e.ExceptionObject); 67 | } 68 | } 69 | 70 | /// 71 | /// Starts this instance. 72 | /// 73 | /// 74 | public bool Start() 75 | { 76 | return m_AppServer.Start(); 77 | } 78 | 79 | /// 80 | /// Stops this instance. 81 | /// 82 | public void Stop() 83 | { 84 | m_AppServer.Stop(); 85 | } 86 | 87 | AppServerMetadata IManagedAppBase.GetMetadata() 88 | { 89 | return m_AppServer.GetMetadata(); 90 | } 91 | 92 | /// 93 | /// Gets the name. 94 | /// 95 | public string Name 96 | { 97 | get { return m_AppServer.Name; } 98 | } 99 | 100 | /// 101 | /// Obtains a lifetime service object to control the lifetime policy for this instance. 102 | /// Return null, never expire 103 | /// 104 | /// 105 | /// An object of type used to control the lifetime policy for this instance. This is the current lifetime service object for this instance if one exists; otherwise, a new lifetime service object initialized to the value of the property. 106 | /// 107 | /// 108 | /// 109 | /// 110 | public override object InitializeLifetimeService() 111 | { 112 | return null; 113 | } 114 | 115 | public bool CanBeRecycled() 116 | { 117 | return m_AppServer.CanBeRecycled(); 118 | } 119 | 120 | 121 | public StatusInfoCollection CollectStatus() 122 | { 123 | return m_AppServer.CollectStatus(); 124 | } 125 | 126 | public void ReportPotentialConfigChange(IServerConfig config) 127 | { 128 | m_AppServer.ReportPotentialConfigChange(config); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/NRack.Worker/NRack.Worker.Net45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {93A2E31D-9AF3-4C9E-986C-1659309F5436} 8 | Exe 9 | Properties 10 | NRack.Worker 11 | NRack.Worker 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\net45\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\net45\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | 39 | ..\packages\AnyLog.0.1.8\lib\net45\AnyLog.dll 40 | True 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | GlobalAssemblyInfo.cs 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 61 | NRack.Base.Net45 62 | 63 | 64 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45} 65 | NRack.Server.Net45 66 | 67 | 68 | 69 | 70 | 71 | 72 | 79 | -------------------------------------------------------------------------------- /src/NRack.Worker/NRack.Worker.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {93A2E31D-9AF3-4C9E-986C-1659309F5436} 8 | Exe 9 | Properties 10 | NRack.Worker 11 | NRack.Worker 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\net40\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\net40\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\AnyLog.0.1.8\lib\net40\AnyLog.dll 38 | True 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | GlobalAssemblyInfo.cs 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4} 59 | NRack.Base 60 | 61 | 62 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45} 63 | NRack.Server 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /src/NRack.Worker/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Runtime.Remoting; 8 | using System.Runtime.Remoting.Channels; 9 | using System.Runtime.Remoting.Channels.Ipc; 10 | using System.Runtime.Serialization.Formatters; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using NRack.Base; 14 | using NRack.Server; 15 | using NRack.Server.Isolation; 16 | using NRack.Server.Isolation.ProcessIsolation; 17 | 18 | namespace NRack.Worker 19 | { 20 | class Program 21 | { 22 | static void Main(string[] args) 23 | { 24 | if (args == null) 25 | throw new ArgumentNullException("args"); 26 | 27 | if (args.Length != 1) 28 | throw new ArgumentException("Arguments number doesn't match!", "args"); 29 | 30 | var name = args[0]; 31 | 32 | if (string.IsNullOrEmpty(name)) 33 | throw new Exception("Name cannot be null or empty."); 34 | 35 | name = name.Trim('"'); 36 | 37 | var channelPort = string.Format(ProcessAppConst.PortNameTemplate, name, Process.GetCurrentProcess().Id); 38 | 39 | var currentDomain = AppDomain.CurrentDomain; 40 | 41 | #pragma warning disable 0618 // Type or member is obsolete 42 | currentDomain.SetCachePath(Path.Combine(Path.Combine(currentDomain.BaseDirectory, IsolationAppConst.ShadowCopyDir), name)); 43 | currentDomain.SetShadowCopyFiles(); 44 | #pragma warning restore 0618 // Type or member is obsolete 45 | 46 | var root = Path.Combine(Path.Combine(currentDomain.BaseDirectory, ProcessAppConst.WorkingDir), name); 47 | 48 | //Hack to change the default AppDomain's root 49 | if (NRackEnv.IsMono) //for Mono 50 | { 51 | var pro = typeof(AppDomain).GetProperty("SetupInformationNoCopy", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty); 52 | var setupInfo = (AppDomainSetup)pro.GetValue(currentDomain, null); 53 | setupInfo.ApplicationBase = root; 54 | } 55 | else // for .NET 56 | { 57 | currentDomain.SetData("APPBASE", root); 58 | } 59 | 60 | currentDomain.SetData(typeof(IsolationMode).Name, IsolationMode.Process); 61 | 62 | try 63 | { 64 | var serverChannel = new IpcServerChannel("IpcAgent", channelPort, new BinaryServerFormatterSinkProvider { TypeFilterLevel = TypeFilterLevel.Full }); 65 | var clientChannel = new IpcClientChannel(); 66 | ChannelServices.RegisterChannel(serverChannel, false); 67 | ChannelServices.RegisterChannel(clientChannel, false); 68 | RemotingConfiguration.RegisterWellKnownServiceType(typeof(ManagedAppWorker), ProcessAppConst.WorkerRemoteName, WellKnownObjectMode.Singleton); 69 | 70 | Console.WriteLine("Ok"); 71 | 72 | var line = Console.ReadLine(); 73 | 74 | while (!"quit".Equals(line, StringComparison.OrdinalIgnoreCase)) 75 | { 76 | line = Console.ReadLine(); 77 | } 78 | } 79 | catch 80 | { 81 | Console.Write("Failed"); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/NRack.Worker/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("NRack.Worker")] 9 | [assembly: AssemblyDescription("NRack.Worker")] 10 | [assembly: AssemblyConfiguration("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("7847be9c-f944-4933-ba89-610766a3a0b1")] -------------------------------------------------------------------------------- /src/NRack.Worker/packages.NRack.Worker.Net45.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/NRack.Worker/packages.NRack.Worker.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/NRack.build: -------------------------------------------------------------------------------- 1 | 2 | 3 | Release 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/NRack.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NRack 5 | $version$ 6 | NRack 7 | Kerry Jiang 8 | Kerry Jiang 9 | http://www.apache.org/licenses/LICENSE-2.0.html 10 | https://github.com/kerryjiang/NRack 11 | false 12 | NRack is a server application container, which can be used for your back end services' hosting and management. 13 | 14 | Copyright 2016 15 | service container host 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/NRack.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Base", "NRack.Base\NRack.Base.csproj", "{406671C6-5DCB-4B23-BD28-FB02C235EAE4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Server", "NRack.Server\NRack.Server.csproj", "{7800B7EA-FB3A-4305-9EE7-74A7B5744C45}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{6E0C838A-35D5-4D95-B3F0-6D0560F9C2FD}" 11 | ProjectSection(SolutionItems) = preProject 12 | GlobalAssemblyInfo.cs = GlobalAssemblyInfo.cs 13 | EndProjectSection 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Test", "NRack.Test\NRack.Test.csproj", "{B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRack.Worker", "NRack.Worker\NRack.Worker.csproj", "{93A2E31D-9AF3-4C9E-986C-1659309F5436}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {406671C6-5DCB-4B23-BD28-FB02C235EAE4}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {7800B7EA-FB3A-4305-9EE7-74A7B5744C45}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {B145DFCA-3A62-4FC6-A3F1-EA970719DC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {93A2E31D-9AF3-4C9E-986C-1659309F5436}.Release|Any CPU.Build.0 = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(SolutionProperties) = preSolution 42 | HideSolutionNode = FALSE 43 | EndGlobalSection 44 | EndGlobal 45 | --------------------------------------------------------------------------------