[gbrainy] Configurable assembly load plus separate domain for compiler service



commit ae34615b717859ba904840e7ef7cfcd5a48c05fb
Author: Jordi Mas <jmas softcatala org>
Date:   Sat Feb 26 20:47:06 2011 +0100

    Configurable assembly load plus separate domain for compiler service

 src/Clients/Classical/gbrainy.cs                   |    5 ++
 src/Clients/WebForms/Defines.cs                    |    2 +-
 src/Clients/WebForms/Download.aspx                 |    2 +-
 src/Clients/WebForms/Game.aspx.cs                  |    8 ++-
 src/Clients/WebForms/Global.asax.cs                |    8 ++-
 src/Clients/WebForms/LanguageSupport.cs            |    5 +-
 src/Clients/WebForms/MasterPage.master             |   31 +++++----
 src/Clients/WebForms/MasterPage.master.cs          |   17 +++++-
 src/Clients/WebForms/MasterPage.master.designer.cs |    2 +
 src/Clients/WebForms/Status.aspx.cs                |   12 +++-
 src/Clients/WebForms/TranslationsWeb.cs            |   10 +++-
 src/Clients/WebForms/package.sh                    |    1 +
 src/Clients/WebForms/web.config                    |    6 ++
 src/Core/Main/GameManager.cs                       |   30 ++++++---
 src/Core/Main/Xml/CodeEvaluation.cs                |   68 ++++++++++++++++++--
 src/Core/Main/Xml/GameXml.cs                       |    8 ++-
 src/Core/Services/IConfiguration.cs                |    1 +
 17 files changed, 174 insertions(+), 42 deletions(-)
---
diff --git a/src/Clients/Classical/gbrainy.cs b/src/Clients/Classical/gbrainy.cs
index 31d7940..6f37fd0 100755
--- a/src/Clients/Classical/gbrainy.cs
+++ b/src/Clients/Classical/gbrainy.cs
@@ -23,6 +23,7 @@ using Gtk;
 using Mono.Unix;
 using System.Diagnostics;
 using Gdk;
+using System.Reflection;
 
 using gbrainy.Core.Main;
 using gbrainy.Core.Platform;
@@ -789,6 +790,10 @@ namespace gbrainy.Clients.Classical
 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.GamesDefinitions, Defines.DATA_DIR);
 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.GamesGraphics, Defines.DATA_DIR);
 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.ThemesDir, Defines.DATA_DIR);
+			
+			string assemblies_dir;
+			assemblies_dir =  System.IO.Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location);				
+			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.AssembliesDir, assemblies_dir);
 		}
 
 		public static void Main (string [] args)
diff --git a/src/Clients/WebForms/Defines.cs b/src/Clients/WebForms/Defines.cs
index 1ee76ab..4cbb90e 100644
--- a/src/Clients/WebForms/Defines.cs
+++ b/src/Clients/WebForms/Defines.cs
@@ -28,7 +28,7 @@ namespace gbrainy.Clients.WebForms
 		public const string THEMES_DIR = "themes/";
 
 		public const string VERBAL_ANALOGIES = "verbal_analogies.xml";
-		public const string GAME_ASSEMBLY = "bin/gbrainy.Games.dll";
+		public const string GAME_ASSEMBLY = "gbrainy.Games.dll";
 		public const string GAMES_FILE = "games.xml";
 	}
 }
diff --git a/src/Clients/WebForms/Download.aspx b/src/Clients/WebForms/Download.aspx
index 5764f7a..10b2a81 100644
--- a/src/Clients/WebForms/Download.aspx
+++ b/src/Clients/WebForms/Download.aspx
@@ -7,7 +7,7 @@
 <p>You can download gbrainy from the following links:</p>
 <ul>
 <li><a href="http://live.gnome.org/gbrainy#Download";>Linux</a></li>
-<li><a href="http://live.gnome.org/gbrainy/Windows";>Windows</a></li>
+<li><a href="https://sourceforge.net/projects/gbrainy/files/gbrainy/";>Windows</a></li>
 </ul>
 </asp:Content> 
 
diff --git a/src/Clients/WebForms/Game.aspx.cs b/src/Clients/WebForms/Game.aspx.cs
index 74d7537..a9520c9 100644
--- a/src/Clients/WebForms/Game.aspx.cs
+++ b/src/Clients/WebForms/Game.aspx.cs
@@ -48,6 +48,7 @@ namespace gbrainy.Clients.WebForms
 			manager = new GameManager ();
 			manager.LoadAssemblyGames (Defines.GAME_ASSEMBLY);
 			manager.LoadVerbalAnalogies (System.IO.Path.Combine ("data/", Defines.VERBAL_ANALOGIES));
+			manager.LoadGamesFromXml (System.IO.Path.Combine ("data/", "games.xml"));
 
 			manager.Difficulty = gbrainy.Core.Main.GameDifficulty.Medium;
 			manager.GameType = gbrainy.Core.Main.GameSession.Types.LogicPuzzles |
@@ -97,7 +98,7 @@ namespace gbrainy.Clients.WebForms
 			Logger.Debug ("Game.Page_Load. Page load starts. Session ID {0}, IsPostBack {1}", Session.SessionID,
 				IsPostBack);
 
-			HtmlForm form = (HtmlForm) Master.FindControl("main_form");
+			HtmlForm form = (HtmlForm) Master.FindControl ("main_form");
 			form.DefaultButton = answer_button.UniqueID;
 
 			if (WebSession.GameState == null)
@@ -107,6 +108,7 @@ namespace gbrainy.Clients.WebForms
 				session.GameManager = CreateManager ();
 				session.New ();
 				WebSession.GameState = session;
+				Global.TotalGamesSessions++;
 
 				_game = GetNextGame ();
 				UpdateGame ();
@@ -142,7 +144,7 @@ namespace gbrainy.Clients.WebForms
 		void InitPage ()
 		{
 			TranslationsWeb service = (TranslationsWeb) ServiceLocator.Instance.GetService <ITranslations> ();
-			service.GetLanguageFromSession = GetLanguageFromSessionHandler;
+			service.OnGetLanguageFromSession = GetLanguageFromSessionHandler;
 
 			game_image.Width = image_width;
 			game_image.Height = image_height;
@@ -302,7 +304,7 @@ namespace gbrainy.Clients.WebForms
 			if (session != null)
 				session.End ();
 			
-			Global.TotalGamesSessions++;
+			Global.TotalEndedSessions++;			
 			Global.TotalGames += session.History.GamesPlayed;
 			Global.TotalTimeSeconds += session.GameTime.Seconds;
 
diff --git a/src/Clients/WebForms/Global.asax.cs b/src/Clients/WebForms/Global.asax.cs
index ca55153..109b6f2 100644
--- a/src/Clients/WebForms/Global.asax.cs
+++ b/src/Clients/WebForms/Global.asax.cs
@@ -16,6 +16,7 @@ namespace gbrainy.Clients.WebForms
 	{
 		// Application counters
 		static public int TotalSessions { get; set; }
+		static public int TotalEndedSessions { get; set; }
 		static public int TotalGamesSessions { get; set; }
 		static public int TotalGames { get; set; }
 		static public int TotalTimeSeconds { get; set; }
@@ -39,9 +40,14 @@ namespace gbrainy.Clients.WebForms
 				Logger.LogDevice = new ConsoleLogger ();
 			}
 			
-			// Setup core services
+			// Register services
 			ServiceLocator.Instance.RegisterService <ITranslations> (new TranslationsWeb ());
+			ServiceLocator.Instance.RegisterService <IConfiguration> (new MemoryConfiguration ());
 			ThemeManager.ConfigPath = Defines.THEMES_DIR;
+			
+			// Configuration
+			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.GamesGraphics, "images/");	
+			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.AssembliesDir, "bin/");
 
 			Logger.Info ("Global.Application_Start.gbrainy web starting");
 		}
diff --git a/src/Clients/WebForms/LanguageSupport.cs b/src/Clients/WebForms/LanguageSupport.cs
index 1b2448b..d9faa75 100644
--- a/src/Clients/WebForms/LanguageSupport.cs
+++ b/src/Clients/WebForms/LanguageSupport.cs
@@ -60,7 +60,7 @@ namespace gbrainy.Clients.WebForms
 		// List of exposed locales
 		static Language [] languages =
 		{
-			new Language ("English", "en_US.utf8"),
+			new Language ("English", "en_US.utf8"), // English always the first one, used as default
 			new Language ("Afrikaans", "af_ZA.utf8"),
 			new Language ("Catalan", "ca_ES.utf8"),
 			new Language ("Czech", "cs_CZ.utf8"),
@@ -88,6 +88,9 @@ namespace gbrainy.Clients.WebForms
 
 		static public Language GetFromCode (string code)
 		{
+			if (langmap.ContainsKey (code) == false)
+				return languages [0];
+			
 			return langmap [code];
 		}
 	}
diff --git a/src/Clients/WebForms/MasterPage.master b/src/Clients/WebForms/MasterPage.master
index 09279b4..6524b74 100644
--- a/src/Clients/WebForms/MasterPage.master
+++ b/src/Clients/WebForms/MasterPage.master
@@ -6,21 +6,24 @@
 	<link href="styles.css" rel="stylesheet" type="text/css"/>
 	<link rel="shortcut icon" href="images/gbrainy.ico" />
 	
-	<script type="text/javascript">
-
-	   var _gaq = _gaq || [];
-	   _gaq.push(['_setAccount', 'UA-619579-3']);
-	   _gaq.push(['_trackPageview']);
+	<asp:ContentPlaceHolder Id="analytics" runat="server" Visible = "false">
+		<script type="text/javascript">
+	
+		   var _gaq = _gaq || [];
+		   _gaq.push(['_setAccount', 'UA-619579-3']);
+		   _gaq.push(['_trackPageview']);
+		
+		   (function() {
+		     var ga = document.createElement('script'); ga.type = 
+		'text/javascript'; ga.async = true;
+		     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 
+		'http://www') + '.google-analytics.com/ga.js';
+		     var s = document.getElementsByTagName('script')[0]; 
+		s.parentNode.insertBefore(ga, s);
+		   })();
+		</script>
+	</asp:ContentPlaceHolder>
 	
-	   (function() {
-	     var ga = document.createElement('script'); ga.type = 
-	'text/javascript'; ga.async = true;
-	     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 
-	'http://www') + '.google-analytics.com/ga.js';
-	     var s = document.getElementsByTagName('script')[0]; 
-	s.parentNode.insertBefore(ga, s);
-	   })();
-	</script>
 </head>
 <body>
 <form runat="server" id = "main_form">
diff --git a/src/Clients/WebForms/MasterPage.master.cs b/src/Clients/WebForms/MasterPage.master.cs
index c232f25..9c5d06d 100644
--- a/src/Clients/WebForms/MasterPage.master.cs
+++ b/src/Clients/WebForms/MasterPage.master.cs
@@ -19,11 +19,14 @@
 
 using System;
 using System.Web;
+using System.Configuration;
 
 namespace gbrainy.Clients.WebForms
 {
 	public partial class MasterPage : System.Web.UI.MasterPage
 	{
+		static string PRODUCTION = "production";
+		static bool ?includeGoogleAnalytics = null;
 
 		// Instead of Page_Load we do Page_Init (Executed before)
 		// To make sure that this code is executed before Page_Load the first page load
@@ -33,8 +36,20 @@ namespace gbrainy.Clients.WebForms
 
 			if (IsPostBack == true)
 				return;
-
 			
+			analytics.Visible = IncludeGoogleAnalytics;			
+		}
+		
+		public bool IncludeGoogleAnalytics {
+			get {
+				if (includeGoogleAnalytics != null)
+					return includeGoogleAnalytics == true;
+				
+				var content = ConfigurationSettings.AppSettings [PRODUCTION];
+				
+				includeGoogleAnalytics = (content == "1");
+				return includeGoogleAnalytics == true;
+			}		
 		}
 	}
 }
diff --git a/src/Clients/WebForms/MasterPage.master.designer.cs b/src/Clients/WebForms/MasterPage.master.designer.cs
index feef474..9bd4b47 100644
--- a/src/Clients/WebForms/MasterPage.master.designer.cs
+++ b/src/Clients/WebForms/MasterPage.master.designer.cs
@@ -13,6 +13,8 @@ namespace gbrainy.Clients.WebForms {
 	
 	public partial class MasterPage {
 		
+		protected System.Web.UI.WebControls.ContentPlaceHolder analytics;
+		
 		protected System.Web.UI.HtmlControls.HtmlForm main_form;
 		
 		protected System.Web.UI.WebControls.ContentPlaceHolder main_placeholder;
diff --git a/src/Clients/WebForms/Status.aspx.cs b/src/Clients/WebForms/Status.aspx.cs
index 2d1cea7..8996bce 100644
--- a/src/Clients/WebForms/Status.aspx.cs
+++ b/src/Clients/WebForms/Status.aspx.cs
@@ -87,9 +87,19 @@ namespace gbrainy.Clients.WebForms
 			application_table.Rows.Add (r);	
 			
 			r = new TableRow ();
-			AddCell (r, "Total sessions");
+			AddCell (r, "Total sessions (as assigned by .Net)");
 			AddCell (r, Global.TotalSessions.ToString ());
 			application_table.Rows.Add (r);
+			
+			r = new TableRow ();
+			AddCell (r, "Total started game sessions");
+			AddCell (r, Global.TotalGamesSessions.ToString ());
+			application_table.Rows.Add (r);
+			
+			r = new TableRow ();
+			AddCell (r, "Total ended game sessions");
+			AddCell (r, Global.TotalEndedSessions.ToString ());
+			application_table.Rows.Add (r);
 				
 			r = new TableRow ();
 			AddCell (r, "Total games played");
diff --git a/src/Clients/WebForms/TranslationsWeb.cs b/src/Clients/WebForms/TranslationsWeb.cs
index 36e0c2b..bd036cc 100644
--- a/src/Clients/WebForms/TranslationsWeb.cs
+++ b/src/Clients/WebForms/TranslationsWeb.cs
@@ -30,12 +30,20 @@ namespace gbrainy.Clients.WebForms
 		public delegate string GetLanguageFromSessionHandler ();
 		static readonly object sync = new object ();
 
-		public GetLanguageFromSessionHandler GetLanguageFromSession;
+		public GetLanguageFromSessionHandler OnGetLanguageFromSession;
 
 		public void Init (string package, string localedir)
 		{
 			Catalog.Init (package, localedir);
 		}
+		
+		string GetLanguageFromSession ()
+		{
+			if (OnGetLanguageFromSession == null)
+				return LanguageSupport.Languages [0].LangCode;
+			
+			return OnGetLanguageFromSession ();
+		}
 
 		public string GetString (string s)
 		{
diff --git a/src/Clients/WebForms/package.sh b/src/Clients/WebForms/package.sh
index ca5ee47..a92047a 100755
--- a/src/Clients/WebForms/package.sh
+++ b/src/Clients/WebForms/package.sh
@@ -20,6 +20,7 @@ cp ../*.asax .
 cp ../web.config .
 
 cp ../bin/*.dll bin
+cp ../bin/*.config bin
 cp ../../../../data/*.xml data
 cp ../../../../data/game-graphics/* images
 cp ../../../../data/app-graphics/* images
diff --git a/src/Clients/WebForms/web.config b/src/Clients/WebForms/web.config
index e5d367d..7065a94 100644
--- a/src/Clients/WebForms/web.config
+++ b/src/Clients/WebForms/web.config
@@ -30,4 +30,10 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
     <pages>
     </pages>
   </system.web>
+
+    <!-- Used to decide if Google Analytics is shown -->
+    <appSettings>
+      <add key="Production" value="1" />
+    </appSettings>
+
 </configuration>
diff --git a/src/Core/Main/GameManager.cs b/src/Core/Main/GameManager.cs
index b40e61f..35e5361 100644
--- a/src/Core/Main/GameManager.cs
+++ b/src/Core/Main/GameManager.cs
@@ -152,6 +152,17 @@ namespace gbrainy.Core.Main
 		public GameLocator [] AvailableGames {
 			get { return available_games.ToArray (); }
 		}
+		
+		// Gives the Assembly.Load used in GamaManager the right path to load the application assemblies
+		static Assembly ResolveAssemblyLoad (object sender, ResolveEventArgs args)
+		{
+			IConfiguration config = ServiceLocator.Instance.GetService <IConfiguration> ();	
+			string asm_dir = config.Get <string> (ConfigurationKeys.AssembliesDir);
+        		string full_name = System.IO.Path.Combine (asm_dir, args.Name);
+			return Assembly.LoadFile (full_name);
+   		}
+		
+		static bool domain_load;
 
 		// Dynamic load of the gbrainy.Games.Dll assembly
 		public void LoadAssemblyGames (string file)
@@ -168,17 +179,14 @@ namespace gbrainy.Core.Main
 
 			try
 			{
-				// Expects the assembly to be in the same dir than this assembly
-				Assembly asm = Assembly.GetExecutingAssembly ();
-				string asm_dir = System.IO.Path.GetDirectoryName (asm.Location);
-#if _ASPNET_	
-				string s = System.IO.Path.GetFileName (file);
-				AssemblyName aname = AssemblyName.GetAssemblyName (file);
-				asem = Assembly.Load (aname);
-#else
-				asem = Assembly.LoadFrom (System.IO.Path.Combine (asm_dir, file));
-#endif				
-
+				if (domain_load == false)
+				{
+					AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler (ResolveAssemblyLoad);
+					domain_load = true;					
+				}
+				
+				asem = Assembly.Load (file);
+				
 				foreach (Type t in asem.GetTypes())
 				{
 					if (t.FullName == CLASS)
diff --git a/src/Core/Main/Xml/CodeEvaluation.cs b/src/Core/Main/Xml/CodeEvaluation.cs
index 1ea211a..df4b79b 100644
--- a/src/Core/Main/Xml/CodeEvaluation.cs
+++ b/src/Core/Main/Xml/CodeEvaluation.cs
@@ -22,15 +22,27 @@ using System.Text;
 using System.Text.RegularExpressions;
 
 using Mono.CSharp;
+using System.Reflection;
+using gbrainy.Core.Services;
 
 namespace gbrainy.Core.Main.Xml
 {
-	// Code evaluation functions
-	public static class CodeEvaluation
+	// This class proxys data from one domain to another
+	public class CrossDomainProxy : MarshalByRefObject
 	{
-		static bool? monofix_needed;
-
-		static public void EvaluateVariables (string code)
+		string code;
+				
+		public void SetCode (string c)
+		{
+			code = c;
+		}
+		
+		public string GetVars ()
+		{
+			return Evaluator.GetVars ();
+		}
+		
+		public void EvaluateVariables ()
 		{
 			string eval;
 
@@ -53,7 +65,51 @@ namespace gbrainy.Core.Main.Xml
 				Console.WriteLine ("GameXml. Error in games.xml: {0} when evaluating variable definition [{1}]", e.Message, code);
 			}
 		}
+	}
 
+	// Code evaluation functions
+	public static class CodeEvaluation
+	{
+		static bool? monofix_needed;
+		static string stored_vars;
+		static int unload_domain = 0;
+		static AppDomain tempDomain;
+		const int maximum_uses = 5;
+		
+		static public void EvaluateVariables (string c)
+		{
+			if (tempDomain == null)
+				tempDomain = AppDomain.CreateDomain ("MonoCSharpDomain");
+			
+			// Load the Mono Compiler service in a separate domain then
+			// we can recycle it to reduce memory consumption
+			//
+			// After Mono 2.12 this is no longer need
+			// http://tirania.org/blog/archive/2011/Feb-24.html			 			
+			IConfiguration config = ServiceLocator.Instance.GetService <IConfiguration> ();	
+			string asm_dir = config.Get <string> (ConfigurationKeys.AssembliesDir);
+			string full_name = System.IO.Path.Combine (asm_dir, "gbrainy.Core.dll");
+			AssemblyName aname = AssemblyName.GetAssemblyName (full_name);
+			Assembly asem = tempDomain.Load (aname);
+			
+  			CrossDomainProxy proxy = (CrossDomainProxy) tempDomain.CreateInstanceAndUnwrap(asem.FullName, 
+				typeof (CrossDomainProxy).FullName);
+   			
+			proxy.SetCode (c);
+			tempDomain.DoCallBack (proxy.EvaluateVariables);
+			stored_vars = proxy.GetVars ();
+			
+					
+			if (unload_domain > maximum_uses)
+			{			
+				AppDomain.Unload (tempDomain);
+				unload_domain = 0;
+				tempDomain = null;
+			}
+			else 
+				unload_domain++;
+		}
+		
 		static public string ReplaceVariables (string str)
 		{
 			const string exp = "\\[[a-z_]+\\]+";
@@ -67,7 +123,7 @@ namespace gbrainy.Core.Main.Xml
 			regex = new Regex (exp, RegexOptions.IgnoreCase);
 			match = regex.Match (str);
 
-			vars = Evaluator.GetVars ();
+			vars = stored_vars;
 			vars = FixGetVars (vars);
 
 			while (String.IsNullOrEmpty (match.Value) == false)
diff --git a/src/Core/Main/Xml/GameXml.cs b/src/Core/Main/Xml/GameXml.cs
index 0230f6b..f2fce4f 100644
--- a/src/Core/Main/Xml/GameXml.cs
+++ b/src/Core/Main/Xml/GameXml.cs
@@ -452,7 +452,13 @@ namespace gbrainy.Core.Main.Xml
 
 					if (String.IsNullOrEmpty (image.Filename) == false)
 					{
-						gr.DrawImageFromFile (Path.Combine (Defines.DATA_DIR, image.Filename),
+						string dir;
+						IConfiguration config;
+
+						config = ServiceLocator.Instance.GetService <IConfiguration> ();
+						dir = config.Get <string> (ConfigurationKeys.GamesGraphics);
+
+						gr.DrawImageFromFile (Path.Combine (dir, image.Filename),
 							image.X, image.Y, image.Width, image.Height);
 					}
 				}
diff --git a/src/Core/Services/IConfiguration.cs b/src/Core/Services/IConfiguration.cs
index 694165b..4e9e053 100644
--- a/src/Core/Services/IConfiguration.cs
+++ b/src/Core/Services/IConfiguration.cs
@@ -24,6 +24,7 @@ namespace gbrainy.Core.Services
 		GamesDefinitions,	// Analogies.xml and games.xml
 		GamesGraphics,
 		ThemesDir,
+		AssembliesDir,
 	};
 
 	public interface IConfiguration : IService



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]