From 7797960cfed0d536dde07aa5364bc3b8b5246f0e Mon Sep 17 00:00:00 2001 From: joeshaw Date: Wed, 25 Oct 2006 19:39:45 +0000 Subject: [PATCH] Fix a bunch of memory problems in beagle: * Fix the usage of assembly.GetTypes() - Mono never GCs Type objects, and calling GetTypes() instantiates evrey one of them contained in an assembly. Paired with some code that walked all the loaded assemblies, we were instantiating thousands of types unnecessarily that stayed around forever. * Remove ReflectionFu methods that get all types that subclass from a type or implement an interface; methods that do this should find a different way. * Implement assembly-scoped attributes for all of our dynamically loaded types, including Queryables, Filters, Tiles, RequestMessages, ResponseMessages, RequestMessageExecutors, and components in the Thunderbird backend. This means that these types now have to register themselves to be loaded, but they can still be dynamically loaded from outside assemblies. * No longer run mono with --debug unless the --mono-debug variable is passed to beagled. This saves us some memory off the top, but there is also some evidence that Mono leaks memory when this is turned on. For me, these changes result in about a 40% reduction in startup memory. --- .../IQueryable.cs => BeagleClient/AssemblyInfo.cs | 54 +++++++------- BeagleClient/Makefile.am | 1 + BeagleClient/Message.cs | 25 +++++-- Filters/AssemblyInfo.cs | 84 ++++++++++++++++++++++ Filters/Makefile.am | 1 + Util/Makefile.am | 1 + Util/ReflectionFu.cs | 24 ++----- .../IQueryable.cs => Util/TypeCacheAttribute.cs | 34 ++++----- beagled/AssemblyInfo.cs | 67 +++++++++++++++++ beagled/BeagleDaemon.cs | 5 +- ...eryable.cs => EvolutionBackendsAssemblyInfo.cs} | 34 +++------ beagled/EvolutionMailDriver/EvolutionMailDriver.cs | 2 - beagled/Filter.cs | 5 ++ beagled/FilterFactory.cs | 2 +- beagled/IQueryable.cs | 8 ++- beagled/IndexHelper/RemoteIndexerExecutor.cs | 4 ++ beagled/Makefile.am | 3 +- beagled/QueryDriver.cs | 52 ++++++-------- beagled/Server.cs | 20 +++--- beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs | 20 +++++- .../ThunderbirdQueryable/ThunderbirdQueryable.cs | 3 + beagled/beagled-index-helper.in | 4 +- beagled/beagled.in | 10 +-- bludgeon/Toolbox.cs | 5 +- search/Makefile.am | 1 + .../IQueryable.cs => search/Tiles/AssemblyInfo.cs | 49 +++++++------ search/Tiles/TileActivator.cs | 14 +++- tools/Config.cs | 5 +- tools/Info.cs | 6 +- tools/Query.cs | 6 +- 30 files changed, 361 insertions(+), 188 deletions(-) copy beagled/IQueryable.cs => BeagleClient/AssemblyInfo.cs (60%) create mode 100644 Filters/AssemblyInfo.cs copy beagled/IQueryable.cs => Util/TypeCacheAttribute.cs (73%) create mode 100644 beagled/AssemblyInfo.cs copy beagled/{IQueryable.cs => EvolutionBackendsAssemblyInfo.cs} (71%) copy beagled/IQueryable.cs => search/Tiles/AssemblyInfo.cs (63%) diff --git a/beagled/IQueryable.cs b/BeagleClient/AssemblyInfo.cs similarity index 60% copy from beagled/IQueryable.cs copy to BeagleClient/AssemblyInfo.cs index e4d3f100..d31ab87d 100644 --- a/beagled/IQueryable.cs +++ b/BeagleClient/AssemblyInfo.cs @@ -1,7 +1,7 @@ // -// IQueryable.cs +// AssemblyInfo.cs // -// Copyright (C) 2004 Novell, Inc. +// Copyright (C) 2006 Novell, Inc. // // @@ -24,28 +24,28 @@ // DEALINGS IN THE SOFTWARE. // - -using System; -using System.Collections; - -namespace Beagle.Daemon { - - public interface IQueryable { - - void Start (); - - bool AcceptQuery (Query query); - - void DoQuery (Query query, - IQueryResult result, - IQueryableChangeData data); - - string GetSnippet (string[] query_terms, Hit hit); - - QueryableStatus GetQueryableStatus (); - } - - public interface IQueryableChangeData { - - } -} +using System.Reflection; + +using Beagle; + +// Any request message types in the Beagle.dll file must be registered here. +[assembly: RequestMessageTypes ( + typeof (IndexingServiceRequest), + typeof (Query), + typeof (DaemonInformationRequest), + typeof (ShutdownRequest), + typeof (ReloadConfigRequest), + typeof (OptimizeIndexesRequest), + typeof (SnippetRequest) +)] + +[assembly: ResponseMessageTypes ( + typeof (EmptyResponse), + typeof (ErrorResponse), + typeof (HitsAddedResponse), + typeof (HitsSubtractedResponse), + typeof (FinishedResponse), + typeof (SearchTermResponse), + typeof (DaemonInformationResponse), + typeof (SnippetResponse) +)] diff --git a/BeagleClient/Makefile.am b/BeagleClient/Makefile.am index 47e42daf..361b244b 100644 --- a/BeagleClient/Makefile.am +++ b/BeagleClient/Makefile.am @@ -10,6 +10,7 @@ CSFLAGS = \ $(BEAGLE_DEFINES) CSFILES = \ + $(srcdir)/AssemblyInfo.cs \ $(srcdir)/Client.cs \ $(srcdir)/Hit.cs \ $(srcdir)/IIndexableGenerator.cs \ diff --git a/BeagleClient/Message.cs b/BeagleClient/Message.cs index 0fad3b2a..70ee301b 100644 --- a/BeagleClient/Message.cs +++ b/BeagleClient/Message.cs @@ -35,12 +35,12 @@ using Beagle.Util; namespace Beagle { public abstract class Message { - protected static Type[] GetTypes (Type parent_type) + protected static Type[] GetTypes (Type parent_type, Type attr_type) { ArrayList types = new ArrayList (); - + foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies ()) - types.AddRange (ReflectionFu.ScanAssemblyForClass (ass, parent_type)); + types.AddRange (ReflectionFu.GetTypesFromAssemblyAttribute (ass, attr_type)); return (Type[]) types.ToArray (typeof (Type)); } @@ -101,7 +101,7 @@ namespace Beagle { get { lock (type_lock) { if (request_types == null) - request_types = GetTypes (typeof (RequestMessage)); + request_types = GetTypes (typeof (RequestMessage), typeof (RequestMessageTypesAttribute)); } return request_types; @@ -231,7 +231,7 @@ namespace Beagle { get { lock (type_lock) { if (response_types == null) - response_types = GetTypes (typeof (ResponseMessage)); + response_types = GetTypes (typeof (ResponseMessage), typeof (ResponseMessageTypesAttribute)); } return response_types; @@ -298,4 +298,19 @@ namespace Beagle { return sb.ToString (); } } + + [AttributeUsage (AttributeTargets.Assembly)] + public class RequestMessageTypesAttribute : TypeCacheAttribute { + public RequestMessageTypesAttribute (params Type[] message_types) : base (message_types) { } + } + + [AttributeUsage (AttributeTargets.Assembly)] + public class ResponseMessageTypesAttribute : TypeCacheAttribute { + public ResponseMessageTypesAttribute (params Type[] message_types) : base (message_types) { } + } + + [AttributeUsage (AttributeTargets.Assembly)] + public class RequestMessageExecutorTypesAttribute : TypeCacheAttribute { + public RequestMessageExecutorTypesAttribute (params Type[] executor_types) : base (executor_types) { } + } } diff --git a/Filters/AssemblyInfo.cs b/Filters/AssemblyInfo.cs new file mode 100644 index 00000000..317e856e --- /dev/null +++ b/Filters/AssemblyInfo.cs @@ -0,0 +1,84 @@ +// +// AssemblyInfo.cs +// +// Copyright (C) 2006 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +using System; + +using Beagle.Filters; + +// All filter types have to be listed here to be loaded. +[assembly: Beagle.Daemon.FilterTypes ( + typeof(FilterAbiWord), + typeof(FilterBMP), + typeof(FilterBoo), + typeof(FilterC), + typeof(FilterChm), + typeof(FilterCpp), + typeof(FilterCSharp), + typeof(FilterDeb), + typeof(FilterDesktop), + typeof(FilterDirectory), + typeof(FilterDOC), + typeof(FilterDocbook), + typeof(FilterEbuild), + typeof(FilterExternal), + typeof(FilterFortran), + typeof(FilterGif), + typeof(FilterHtml), + typeof(FilterImLog), + typeof(FilterJava), + typeof(FilterJavascript), + typeof(FilterJpeg), + typeof(FilterKAddressBook), + typeof(FilterKnotes), + typeof(FilterKonqHistory), + typeof(FilterLabyrinth), + typeof(FilterMail), + typeof(FilterMan), + typeof(FilterMatlab), + typeof(FilterMonodoc), + typeof(FilterMPlayerVideo), + typeof(FilterMusic), + typeof(FilterOpenOffice), + typeof(FilterPascal), + typeof(FilterPdf), + typeof(FilterPerl), + typeof(FilterPhp), + typeof(FilterPng), + typeof(FilterPPT), + typeof(FilterPython), + typeof(FilterRPM), + typeof(FilterRTF), + typeof(FilterRuby), + typeof(FilterScheme), + typeof(FilterScilab), + typeof(FilterShellscript), + typeof(FilterSpreadsheet), + typeof(FilterSvg), + typeof(FilterText), + typeof(FilterTiff), + typeof(FilterTotem), + typeof(FilterXslt) +)] \ No newline at end of file diff --git a/Filters/Makefile.am b/Filters/Makefile.am index b34ae7cc..c6d36561 100644 --- a/Filters/Makefile.am +++ b/Filters/Makefile.am @@ -21,6 +21,7 @@ HAP_CSFILES = \ include entagged-sharp/entagged-sharp.sources CSFILES = \ + AssemblyInfo.cs \ $(ENTAGGED_CSFILES) \ $(HAP_CSFILES) \ $(srcdir)/FilterHtml.cs \ diff --git a/Util/Makefile.am b/Util/Makefile.am index 11dc1d4e..9f1b3f59 100644 --- a/Util/Makefile.am +++ b/Util/Makefile.am @@ -82,6 +82,7 @@ UTIL_CSFILES = \ $(srcdir)/Tiff.cs \ $(srcdir)/Timeline.cs \ $(srcdir)/TopScores.cs \ + $(srcdir)/TypeCacheAttribute.cs \ $(srcdir)/UnclosableStream.cs \ $(srcdir)/UriFu.cs \ $(srcdir)/XdgMime.cs \ diff --git a/Util/ReflectionFu.cs b/Util/ReflectionFu.cs index 5d023545..9d834838 100644 --- a/Util/ReflectionFu.cs +++ b/Util/ReflectionFu.cs @@ -92,28 +92,16 @@ namespace Beagle.Util { return assemblies; } - static public ArrayList ScanAssemblyForClass (Assembly assembly, Type supertype) + static public ArrayList GetTypesFromAssemblyAttribute (Assembly assembly, Type attr_type) { - ArrayList subclasses = new ArrayList (); + ArrayList types = new ArrayList (); - foreach (Type t in assembly.GetTypes ()) { - if (t.IsSubclassOf (supertype) && ! t.IsAbstract) - subclasses.Add (t); - } - - return subclasses; - } + TypeCacheAttribute attr = (TypeCacheAttribute) Attribute.GetCustomAttribute (assembly, attr_type); - static public ArrayList ScanAssemblyForInterface (Assembly assembly, Type iface) - { - ArrayList implementors = new ArrayList (); - - foreach (Type t in assembly.GetTypes ()) { - if (t.GetInterface (iface.ToString ()) != null) - implementors.Add (t); - } + if (attr != null) + types.AddRange (attr.Types); - return implementors; + return types; } static public ArrayList ScanTypeForAttribute (Type type, Type attribute_type) diff --git a/beagled/IQueryable.cs b/Util/TypeCacheAttribute.cs similarity index 73% copy from beagled/IQueryable.cs copy to Util/TypeCacheAttribute.cs index e4d3f100..3cbc9e58 100644 --- a/beagled/IQueryable.cs +++ b/Util/TypeCacheAttribute.cs @@ -1,7 +1,7 @@ // -// IQueryable.cs +// TypeCacheAttribute.cs // -// Copyright (C) 2004 Novell, Inc. +// Copyright (C) 2006 Novell, Inc. // // @@ -24,28 +24,22 @@ // DEALINGS IN THE SOFTWARE. // - using System; using System.Collections; +using System.Reflection; -namespace Beagle.Daemon { - - public interface IQueryable { - - void Start (); +namespace Beagle.Util { - bool AcceptQuery (Query query); + public abstract class TypeCacheAttribute : Attribute { + private Type[] types; - void DoQuery (Query query, - IQueryResult result, - IQueryableChangeData data); - - string GetSnippet (string[] query_terms, Hit hit); - - QueryableStatus GetQueryableStatus (); - } + public TypeCacheAttribute (params Type[] types) + { + this.types = types; + } - public interface IQueryableChangeData { - + public ICollection Types { + get { return this.types; } + } } -} +} \ No newline at end of file diff --git a/beagled/AssemblyInfo.cs b/beagled/AssemblyInfo.cs new file mode 100644 index 00000000..bf16faf3 --- /dev/null +++ b/beagled/AssemblyInfo.cs @@ -0,0 +1,67 @@ +// +// AssemblyInfo.cs +// +// Copyright (C) 2006 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +using System.Reflection; + +using Beagle; +using Beagle.Daemon; + +// Any request message types in the BeagleDaemonLib.dll file must be registered +// in these two attributes. +[assembly: RequestMessageTypes ( + typeof (RemoteIndexerRequest) +)] + +[assembly: ResponseMessageTypes ( + typeof (RemoteIndexerResponse) +)] + +// Executors go in here. +[assembly: RequestMessageExecutorTypes ( + typeof (DaemonInformationExecutor), + typeof (OptimizeIndexesExecutor), + typeof (ReloadConfigExecutor), + typeof (ShutdownExecutor), + typeof (SnippetExecutor) +)] + +// All backends in this assembly must be registered here. +[assembly: IQueryableTypes ( + typeof (Beagle.Daemon.KMailQueryable.KMailQueryable), + typeof (Beagle.Daemon.FileSystemQueryable.FileSystemQueryable), + typeof (Beagle.Daemon.GaimLogQueryable.GaimLogQueryable), + typeof (Beagle.Daemon.IndexingServiceQueryable.IndexingServiceQueryable), + typeof (Beagle.Daemon.TomboyQueryable.TomboyQueryable), + typeof (Beagle.Daemon.LabyrinthQueryable.LabyrinthQueryable), + typeof (Beagle.Daemon.BlamQueryable.BlamQueryable), + typeof (Beagle.Daemon.LifereaQueryable.LifereaQueryable), + typeof (Beagle.Daemon.AkregatorQueryable.AkregatorQueryable), + typeof (Beagle.Daemon.KonqQueryable.KonqQueryable), + typeof (Beagle.Daemon.KNotesQueryable.KNotesQueryable), + typeof (Beagle.Daemon.KabcQueryable.KabcQueryable), + typeof (Beagle.Daemon.KopeteQueryable.KopeteQueryable), + typeof (Beagle.Daemon.StaticQueryable) +)] \ No newline at end of file diff --git a/beagled/BeagleDaemon.cs b/beagled/BeagleDaemon.cs index f8f95793..64ec4663 100644 --- a/beagled/BeagleDaemon.cs +++ b/beagled/BeagleDaemon.cs @@ -188,6 +188,8 @@ namespace Beagle.Daemon { Logger.Log.Debug ("Daemon initialization finished after {0}", stopwatch); + SystemInformation.LogMemoryUsage (); + if (arg_indexing_test_mode) { Thread.Sleep (1000); // Ugly paranoia: wait a second for the backends to settle. Logger.Log.Debug ("Running in indexing test mode"); @@ -243,7 +245,8 @@ namespace Beagle.Daemon { case "--heap-buddy": case "--mdb": - // Silently ignore the --heap-buddy argument: it gets handled + case "--mono-debug": + // Silently ignore these arguments: they get handled // in the wrapper script. break; diff --git a/beagled/IQueryable.cs b/beagled/EvolutionBackendsAssemblyInfo.cs similarity index 71% copy from beagled/IQueryable.cs copy to beagled/EvolutionBackendsAssemblyInfo.cs index e4d3f100..843d06f2 100644 --- a/beagled/IQueryable.cs +++ b/beagled/EvolutionBackendsAssemblyInfo.cs @@ -1,9 +1,8 @@ // -// IQueryable.cs +// EvolutionBackendsAssemblyInfo.cs // -// Copyright (C) 2004 Novell, Inc. +// Copyright (C) 2006 Novell, Inc. // - // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -24,28 +23,13 @@ // DEALINGS IN THE SOFTWARE. // - using System; -using System.Collections; - -namespace Beagle.Daemon { - - public interface IQueryable { - - void Start (); - - bool AcceptQuery (Query query); - - void DoQuery (Query query, - IQueryResult result, - IQueryableChangeData data); - - string GetSnippet (string[] query_terms, Hit hit); - QueryableStatus GetQueryableStatus (); - } +using Beagle.Daemon; +using Beagle.Daemon.EvolutionMailDriver; +using Beagle.Daemon.EvolutionDataServerQueryable; - public interface IQueryableChangeData { - - } -} +[assembly: IQueryableTypes ( + typeof (EvolutionMailQueryable), + typeof (EvolutionDataServerQueryable) +)] diff --git a/beagled/EvolutionMailDriver/EvolutionMailDriver.cs b/beagled/EvolutionMailDriver/EvolutionMailDriver.cs index bef78683..63f13171 100644 --- a/beagled/EvolutionMailDriver/EvolutionMailDriver.cs +++ b/beagled/EvolutionMailDriver/EvolutionMailDriver.cs @@ -33,8 +33,6 @@ using System.Threading; using Beagle.Util; using Camel = Beagle.Util.Camel; -using LNI = Lucene.Net.Index; - namespace Beagle.Daemon.EvolutionMailDriver { [QueryableFlavor (Name="EvolutionMail", Domain=QueryDomain.Local, RequireInotify=false)] diff --git a/beagled/Filter.cs b/beagled/Filter.cs index fca85e8b..f51286b5 100644 --- a/beagled/Filter.cs +++ b/beagled/Filter.cs @@ -724,4 +724,9 @@ namespace Beagle.Daemon { get { return this.child_indexables; } } } + + [AttributeUsage (AttributeTargets.Assembly)] + public class FilterTypesAttribute : TypeCacheAttribute { + public FilterTypesAttribute (params Type[] filter_types) : base (filter_types) { } + } } diff --git a/beagled/FilterFactory.cs b/beagled/FilterFactory.cs index 9326adb4..e74ea16e 100644 --- a/beagled/FilterFactory.cs +++ b/beagled/FilterFactory.cs @@ -294,7 +294,7 @@ namespace Beagle.Daemon { { int count = 0; - foreach (Type t in ReflectionFu.ScanAssemblyForClass (assembly, typeof (Filter))) { + foreach (Type t in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (FilterTypesAttribute))) { Filter filter = null; try { diff --git a/beagled/IQueryable.cs b/beagled/IQueryable.cs index e4d3f100..e37d171e 100644 --- a/beagled/IQueryable.cs +++ b/beagled/IQueryable.cs @@ -24,10 +24,11 @@ // DEALINGS IN THE SOFTWARE. // - using System; using System.Collections; +using Beagle.Util; + namespace Beagle.Daemon { public interface IQueryable { @@ -48,4 +49,9 @@ namespace Beagle.Daemon { public interface IQueryableChangeData { } + + [AttributeUsage (AttributeTargets.Assembly)] + public class IQueryableTypesAttribute : TypeCacheAttribute { + public IQueryableTypesAttribute (params Type[] queryable_types) : base (queryable_types) { } + } } diff --git a/beagled/IndexHelper/RemoteIndexerExecutor.cs b/beagled/IndexHelper/RemoteIndexerExecutor.cs index d42c8da4..7bb59a2a 100644 --- a/beagled/IndexHelper/RemoteIndexerExecutor.cs +++ b/beagled/IndexHelper/RemoteIndexerExecutor.cs @@ -28,9 +28,13 @@ using System; using System.Collections; using System.Xml.Serialization; +using Beagle; using Beagle.Util; using Beagle.Daemon; +// Register the executor class +[assembly: RequestMessageExecutorTypes (typeof (Beagle.IndexHelper.RemoteIndexerExecutor))] + namespace Beagle.IndexHelper { [RequestMessage (typeof (RemoteIndexerRequest))] diff --git a/beagled/Makefile.am b/beagled/Makefile.am index bb0dea79..6a281f0c 100644 --- a/beagled/Makefile.am +++ b/beagled/Makefile.am @@ -356,6 +356,7 @@ DAEMON_DLL_CSFILES = \ $(KNOTES_QUERYABLE_CSFILES) \ $(KABC_QUERYABLE_CSFILES) \ $(KOPETE_QUERYABLE_CSFILES) \ + $(srcdir)/AssemblyInfo.cs \ $(srcdir)/FileAttributes.cs \ $(srcdir)/FileAttributesStore.cs \ $(srcdir)/FileAttributesStore_ExtendedAttribute.cs \ @@ -462,7 +463,7 @@ EVO_MAIL_QUERYABLE_CSFILES = \ EVO_DLL_TARGET = EvolutionBackends.dll EVO_DLL_CSFLAGS = $(BACKEND_CSFLAGS) -EVO_DLL_CSFILES = $(EDS_QUERYABLE_CSFILES) $(EVO_MAIL_QUERYABLE_CSFILES) +EVO_DLL_CSFILES = EvolutionBackendsAssemblyInfo.cs $(EDS_QUERYABLE_CSFILES) $(EVO_MAIL_QUERYABLE_CSFILES) EVO_DLL_ASSEMBLIES = $(BACKEND_ASSEMBLIES) $(EVO_LIBS) $(EVO_DLL_TARGET): $(EVO_DLL_CSFILES) $(DAEMON_DLL_LOCAL_ASSEMBLIES) $(DAEMON_DLL_TARGET) diff --git a/beagled/QueryDriver.cs b/beagled/QueryDriver.cs index 9f45c6d0..daab67b2 100644 --- a/beagled/QueryDriver.cs +++ b/beagled/QueryDriver.cs @@ -146,15 +146,15 @@ namespace Beagle.Daemon { return impls.Length > 0; } - // For every type in the assembly that - // (1) implements IQueryable - // (2) Has a QueryableFlavor attribute attached + // Find the types in the assembly that + // (1) register themselves in AssemblyInfo.cs:IQueryableTypes and + // (2) has a QueryableFlavor attribute attached // assemble a Queryable object and stick it into our list of queryables. - static void ScanAssembly (Assembly assembly) + static void ScanAssemblyForQueryables (Assembly assembly) { int count = 0; - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (IQueryable))) { + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (IQueryableTypesAttribute))) { bool type_accepted = false; foreach (QueryableFlavor flavor in ReflectionFu.ScanTypeForAttribute (type, typeof (QueryableFlavor))) { if (! UseQueryable (flavor.Name)) @@ -215,29 +215,21 @@ namespace Beagle.Daemon { ArrayList assemblies = ReflectionFu.ScanEnvironmentForAssemblies ("BEAGLE_FILTER_PATH", PathFinder.FilterDir); foreach (Assembly assembly in assemblies) { - foreach (Type type in assembly.GetTypes ()) - if (type.FullName.StartsWith ("Beagle.Filters")) { - - if (type.IsNestedPrivate || - type.IsNestedPublic || - type.IsNestedAssembly || - type.IsNestedFamily) + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (FilterTypesAttribute))) { + object[] attributes = type.GetCustomAttributes (false); + foreach (object attribute in attributes) { + + PropertyKeywordMapping mapping = attribute as PropertyKeywordMapping; + if (mapping == null) continue; - - object[] attributes = type.GetCustomAttributes (false); - foreach (object attribute in attributes) { - - PropertyKeywordMapping mapping = attribute as PropertyKeywordMapping; - if (mapping == null) - continue; - //Logger.Log.Debug (mapping.Keyword + " => " - // + mapping.PropertyName - // + " is-keyword=" + mapping.IsKeyword + " (" - // + mapping.Description + ") " - // + "(" + type.FullName + ")"); - PropertyKeywordFu.RegisterMapping (mapping); - } + //Logger.Log.Debug (mapping.Keyword + " => " + // + mapping.PropertyName + // + " is-keyword=" + mapping.IsKeyword + " (" + // + mapping.Description + ") " + // + "(" + type.FullName + ")"); + PropertyKeywordFu.RegisterMapping (mapping); } + } } } @@ -334,7 +326,6 @@ namespace Beagle.Daemon { static public void Init () { ReadBackendsFromConf (); - SystemInformation.LogMemoryUsage (); assemblies = ReflectionFu.ScanEnvironmentForAssemblies ("BEAGLE_BACKEND_PATH", PathFinder.BackendDir); } @@ -345,7 +336,7 @@ namespace Beagle.Daemon { assemblies.Add (Assembly.GetExecutingAssembly ()); foreach (Assembly assembly in assemblies) { - ScanAssembly (assembly); + ScanAssemblyForQueryables (assembly); // This allows backends to define their // own executors. @@ -354,9 +345,6 @@ namespace Beagle.Daemon { assemblies = null; - - SystemInformation.LogMemoryUsage (); - ReadKeywordMappings (); LoadSystemIndexes (); @@ -393,7 +381,7 @@ namespace Beagle.Daemon { string ret = "User:\n"; foreach (Assembly assembly in assemblies) { - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (IQueryable))) { + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (IQueryableTypesAttribute))) { foreach (QueryableFlavor flavor in ReflectionFu.ScanTypeForAttribute (type, typeof (QueryableFlavor))) ret += String.Format (" - {0}\n", flavor.Name); } diff --git a/beagled/Server.cs b/beagled/Server.cs index 404dacee..6ea2c307 100644 --- a/beagled/Server.cs +++ b/beagled/Server.cs @@ -315,10 +315,16 @@ namespace Beagle.Daemon { private static Hashtable live_handlers = new Hashtable (); private bool running = false; - public Server (string name) + static Server () { - ScanAssemblyForExecutors (Assembly.GetCallingAssembly ()); + Log.Debug (new System.Diagnostics.StackTrace (true).ToString ()); + + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies ()) + ScanAssemblyForExecutors (assembly); + } + public Server (string name) + { // Use the default name when passed null if (name == null) name = "socket"; @@ -335,7 +341,6 @@ namespace Beagle.Daemon { // Perform expensive serialization all at once. Do this before signal handler is setup. public static void Init () { - ScanAssemblyForExecutors (Assembly.GetExecutingAssembly ()); Shutdown.ShutdownEvent += OnShutdown; ConnectionHandler.Init (); initialized = true; @@ -460,14 +465,7 @@ namespace Beagle.Daemon { return; scanned_assemblies [assembly] = assembly; - foreach (Type t in assembly.GetTypes ()) { - - if (!t.IsSubclassOf (typeof (RequestMessageExecutor))) - continue; - - // Yes, we know it doesn't have a RequestMessageAttribute - if (t == typeof (SimpleRequestMessageExecutor)) - continue; + foreach (Type t in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (RequestMessageExecutorTypesAttribute))) { Attribute attr = Attribute.GetCustomAttribute (t, typeof (RequestMessageAttribute)); diff --git a/beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs b/beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs index 45855c03..b2a04331 100644 --- a/beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs +++ b/beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs @@ -31,8 +31,17 @@ using System.Reflection; using Beagle.Util; using Beagle.Daemon; +using Beagle.Daemon.ThunderbirdQueryable; using TB = Beagle.Util.Thunderbird; +[assembly: ThunderbirdDefinedGenerators ( + typeof (ContactIndexableGenerator), + typeof (MailIndexableGenerator), + typeof (MoveMailIndexableGenerator), + typeof (NntpIndexableGenerator), + typeof (RssIndexableGenerator) +)] + namespace Beagle.Daemon.ThunderbirdQueryable { public class ThunderbirdIndexer { @@ -73,8 +82,8 @@ namespace Beagle.Daemon.ThunderbirdQueryable { private void LoadSupportedTypes () { Assembly assembly = Assembly.GetCallingAssembly (); - - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (IIndexableGenerator))) { + + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (ThunderbirdDefinedGeneratorsAttribute))) { foreach (ThunderbirdIndexableGeneratorAttribute attr in ReflectionFu.ScanTypeForAttribute (type, typeof (ThunderbirdIndexableGeneratorAttribute))) { @@ -432,6 +441,13 @@ namespace Beagle.Daemon.ThunderbirdQueryable { } ///////////////////////////////////////////////////////////////////////////////////// + + [AttributeUsage (AttributeTargets.Assembly)] + public class ThunderbirdDefinedGeneratorsAttribute : TypeCacheAttribute { + public ThunderbirdDefinedGeneratorsAttribute (params Type[] types) : base (types) { } + } + + ///////////////////////////////////////////////////////////////////////////////////// public enum NotificationType { StopIndexing, diff --git a/beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs b/beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs index 5e937687..29997723 100644 --- a/beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs +++ b/beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs @@ -33,6 +33,9 @@ using System.Text.RegularExpressions; using Beagle; using Beagle.Util; +// Register the Thunderbird backend for this assembly. +[assembly: Beagle.Daemon.IQueryableTypes (typeof (Beagle.Daemon.ThunderbirdQueryable.ThunderbirdQueryable))] + namespace Beagle.Daemon.ThunderbirdQueryable { [QueryableFlavor (Name = "Thunderbird", Domain = QueryDomain.Local, RequireInotify = false)] diff --git a/beagled/beagled-index-helper.in b/beagled/beagled-index-helper.in index 60d04365..216e0381 100644 --- a/beagled/beagled-index-helper.in +++ b/beagled/beagled-index-helper.in @@ -24,13 +24,13 @@ if [ -n "$_GET_ON_THE_HEAP_BUDDY_BANDWAGON" ]; then MONO_EXTRA_ARGS="--profile=heap-buddy:$BEAGLE_HEAP_BUDDY_DIR/outfile.helper.$n $MONO_EXTRA_ARGS" fi -if [ -n "$BEAGLE_DEBUG_FLAG_IS_SET" ]; then +if [ -n "$BEAGLE_MONO_DEBUG_FLAG_IS_SET" ]; then MONO_EXTRA_ARGS="--debug $MONO_EXTRA_ARGS" fi export MONO_PATH="$THIS_PATH${MONO_PATH+:$MONO_PATH}" -CMDLINE="mono --debug $MONO_EXTRA_ARGS $THIS_EXE $@" +CMDLINE="$BEAGLE_MONO_RUNTIME $MONO_EXTRA_ARGS $THIS_EXE $@" PROCESS_NAME="beagled-helper" exec -a $PROCESS_NAME $CMDLINE diff --git a/beagled/beagled.in b/beagled/beagled.in index 3490b3ca..b9fda536 100644 --- a/beagled/beagled.in +++ b/beagled/beagled.in @@ -41,7 +41,7 @@ fi monogrind=0 heap_buddy=0 -debug=0 +mono_debug=0 mdb=0 BEAGLED_ARGS="$*" @@ -52,7 +52,7 @@ for i in $BEAGLED_ARGS; do --monogrind ) monogrind=1 ;; --heap-buddy ) heap_buddy=1 ;; --mdb ) mdb=1 ;; - --debug ) debug=1 ;; + --mono-debug ) mono_debug=1 ;; esac done @@ -82,8 +82,8 @@ if [ $heap_buddy -eq 1 ]; then rm -f $BEAGLE_HEAP_BUDDY_DIR/outfile.beagled $BEAGLE_HEAP_BUDDY_DIR/outfile.helper.* fi -if [ $debug -eq 1 ]; then - export BEAGLE_DEBUG_FLAG_IS_SET=1 +if [ $mono_debug -eq 1 ]; then + export BEAGLE_MONO_DEBUG_FLAG_IS_SET=1 MONO_EXTRA_ARGS="--debug $MONO_EXTRA_ARGS" fi @@ -101,7 +101,7 @@ if [ $monogrind -eq 1 ]; then elif [ $mdb -eq 1 ]; then CMDLINE="mdb $TARGET_EXE -args $BEAGLED_ARGS $FGBG_ARG" else - CMDLINE="$BEAGLE_MONO_RUNTIME --debug $MONO_EXTRA_ARGS $TARGET_EXE $BEAGLED_ARGS $FGBG_ARG" + CMDLINE="$BEAGLE_MONO_RUNTIME $MONO_EXTRA_ARGS $TARGET_EXE $BEAGLED_ARGS $FGBG_ARG" fi PROCESS_NAME="beagled" diff --git a/bludgeon/Toolbox.cs b/bludgeon/Toolbox.cs index c9fdf734..1f85d01e 100644 --- a/bludgeon/Toolbox.cs +++ b/bludgeon/Toolbox.cs @@ -123,7 +123,10 @@ namespace Bludgeon { static private void LoadAllPairs (Assembly assembly) { - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (IHammer))) { + foreach (Type type in assembly.GetTypes ()) { // assembly.GetTypes() is very bad. + if (type.GetInterface (typeof (IHammer).ToString ()) == null) + continue; + foreach (HammerAttribute attr in ReflectionFu.ScanTypeForAttribute (type, typeof (HammerAttribute))) { Pair pair; pair = new Pair (); diff --git a/search/Makefile.am b/search/Makefile.am index b9c4ac84..4cd4c6bc 100644 --- a/search/Makefile.am +++ b/search/Makefile.am @@ -40,6 +40,7 @@ CSFILES = \ TILES = \ $(srcdir)/Tiles/ActionMenuItem.cs \ $(srcdir)/Tiles/Application.cs \ + $(srcdir)/Tiles/AssemblyInfo.cs \ $(srcdir)/Tiles/Audio.cs \ $(srcdir)/Tiles/CApplet.cs \ $(srcdir)/Tiles/Calendar.cs \ diff --git a/beagled/IQueryable.cs b/search/Tiles/AssemblyInfo.cs similarity index 63% copy from beagled/IQueryable.cs copy to search/Tiles/AssemblyInfo.cs index e4d3f100..e6c29ac9 100644 --- a/beagled/IQueryable.cs +++ b/search/Tiles/AssemblyInfo.cs @@ -1,7 +1,7 @@ // -// IQueryable.cs +// AssemblyInfo.cs // -// Copyright (C) 2004 Novell, Inc. +// Copyright (C) 2006 Novell, Inc. // // @@ -24,28 +24,27 @@ // DEALINGS IN THE SOFTWARE. // - using System; -using System.Collections; - -namespace Beagle.Daemon { - - public interface IQueryable { - - void Start (); - - bool AcceptQuery (Query query); - - void DoQuery (Query query, - IQueryResult result, - IQueryableChangeData data); - - string GetSnippet (string[] query_terms, Hit hit); - - QueryableStatus GetQueryableStatus (); - } - public interface IQueryableChangeData { - - } -} +using Search.Tiles; + +[assembly: TileActivatorTypes ( + typeof (ApplicationActivator), + typeof (AudioActivator), + typeof (CalendarActivator), + typeof (CAppletActivator), + typeof (ContactActivator), + typeof (FileActivator), + typeof (FolderActivator), + typeof (ImageActivator), + typeof (IMLogActivator), + typeof (MailAttachmentActivator), + typeof (MailMessageActivator), + typeof (NoteActivator), + typeof (PresentationActivator), + typeof (RSSFeedActivator), + typeof (SpreadsheetActivator), + typeof (TextDocumentActivator), + typeof (VideoActivator), + typeof (WebHistoryActivator) +)] diff --git a/search/Tiles/TileActivator.cs b/search/Tiles/TileActivator.cs index ad2a9cbb..f3878ce0 100644 --- a/search/Tiles/TileActivator.cs +++ b/search/Tiles/TileActivator.cs @@ -79,7 +79,14 @@ namespace Search.Tiles { foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies ()) { - foreach (Type type in ReflectionFu.ScanAssemblyForClass (assembly, typeof (TileActivator))) { + bool first = true; + + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (TileActivatorTypesAttribute))) { + if (first) { + Console.WriteLine ("* Assembly: {0}", assembly.FullName); + first = false; + } + Console.WriteLine (" - {0}", type); try { activators.Add ((TileActivator) Activator.CreateInstance (type)); @@ -117,4 +124,9 @@ namespace Search.Tiles { return null; } } + + [AttributeUsage (AttributeTargets.Assembly)] + public class TileActivatorTypesAttribute : TypeCacheAttribute { + public TileActivatorTypesAttribute (params Type[] types) : base (types) { } + } } diff --git a/tools/Config.cs b/tools/Config.cs index 08f7b97c..ced613f9 100644 --- a/tools/Config.cs +++ b/tools/Config.cs @@ -32,6 +32,7 @@ using System.Collections.Specialized; using System.Reflection; using Beagle; +using Beagle.Daemon; using Beagle.Util; //using Gtk; @@ -44,7 +45,7 @@ public static class ConfigTool { string usage = "beagle-config: Command-line interface to the Beagle config file.\n" + "Web page: http://www.gnome.org/projects/beagle\n" + - "Copyright (C) 2005 Novell, Inc.\n\n"; + "Copyright (C) 2005-2006 Novell, Inc.\n\n"; usage += "Usage: beagle-config [OPTIONS]\n" + " or: beagle-config
\n" + @@ -217,7 +218,7 @@ public static class ConfigTool { } foreach (Assembly assembly in assemblies) { - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (Beagle.Daemon.IQueryable))) { + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (IQueryableTypesAttribute))) { foreach (Beagle.Daemon.QueryableFlavor flavor in ReflectionFu.ScanTypeForAttribute (type, typeof (Beagle.Daemon.QueryableFlavor))) backends.Add (flavor.Name); } diff --git a/tools/Info.cs b/tools/Info.cs index 23f97a7e..190e3990 100644 --- a/tools/Info.cs +++ b/tools/Info.cs @@ -42,7 +42,7 @@ class InfoTool { string usage = "beagle-info: Statistics from the Beagle daemon.\n" + "Web page: http://www.gnome.org/projects/beagle\n" + - "Copyright (C) 2004-2005 Novell, Inc.\n\n"; + "Copyright (C) 2004-2006 Novell, Inc.\n\n"; usage += "Usage: beagle-info \n\n" + "Options:\n" + @@ -128,7 +128,7 @@ class InfoTool { static void PrintFilterDetails (Assembly assembly) { StringBuilder sb = new StringBuilder (); - foreach (Type t in ReflectionFu.ScanAssemblyForClass (assembly, typeof (Filter))) { + foreach (Type t in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (FilterTypesAttribute))) { Filter filter = null; try { @@ -190,7 +190,7 @@ class InfoTool { } foreach (Assembly assembly in assemblies) { - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (Beagle.Daemon.IQueryable))) { + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (IQueryableTypesAttribute))) { foreach (Beagle.Daemon.QueryableFlavor flavor in ReflectionFu.ScanTypeForAttribute (type, typeof (Beagle.Daemon.QueryableFlavor))) { Console.WriteLine ("{0,-20} (" + assembly.Location + ")", flavor.Name); } diff --git a/tools/Query.cs b/tools/Query.cs index 89c680d4..52f35a0c 100644 --- a/tools/Query.cs +++ b/tools/Query.cs @@ -1,7 +1,7 @@ // // Query.cs // -// Copyright (C) 2004-2005 Novell, Inc. +// Copyright (C) 2004-2006 Novell, Inc. // // @@ -133,7 +133,7 @@ class QueryTool { string usage = "beagle-query: Command-line interface to the Beagle search system.\n" + "Web page: http://www.gnome.org/projects/beagle\n" + - "Copyright (C) 2004 Novell, Inc.\n\n"; + "Copyright (C) 2004-2006 Novell, Inc.\n\n"; usage += "Usage: beagle-query [OPTIONS] \n\n" + "Options:\n" + @@ -188,7 +188,7 @@ class QueryTool { } foreach (Assembly assembly in assemblies) { - foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (Beagle.Daemon.IQueryable))) { + foreach (Type type in ReflectionFu.GetTypesFromAssemblyAttribute (assembly, typeof (IQueryableTypesAttribute))) { object[] attributes = type.GetCustomAttributes (false); foreach (object attribute in attributes) { PropertyKeywordMapping mapping = attribute as PropertyKeywordMapping; -- 2.11.4.GIT