lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnas...@apache.org
Subject svn commit: r1305232 - in /incubator/lucene.net/trunk: build/vs2008/ build/vs2010/contrib/ src/contrib/MemoryIndex/ src/contrib/MemoryIndex/Properties/
Date Mon, 26 Mar 2012 05:58:27 GMT
Author: pnasser
Date: Mon Mar 26 05:58:26 2012
New Revision: 1305232

URL: http://svn.apache.org/viewvc?rev=1305232&view=rev
Log:
Adding MemoryIndex to contrib - not even close to compiling, but it's a start.

Added:
    incubator/lucene.net/trunk/build/vs2010/contrib/MemoryIndex.sln
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.cs
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.csproj
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexReader.cs
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexTokenStream.cs
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryInfo.cs
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/Properties/
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/Properties/AssemblyInfo.cs
    incubator/lucene.net/trunk/src/contrib/MemoryIndex/VM.cs
Removed:
    incubator/lucene.net/trunk/build/vs2008/

Added: incubator/lucene.net/trunk/build/vs2010/contrib/MemoryIndex.sln
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/build/vs2010/contrib/MemoryIndex.sln?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/build/vs2010/contrib/MemoryIndex.sln (added)
+++ incubator/lucene.net/trunk/build/vs2010/contrib/MemoryIndex.sln Mon Mar 26 05:58:26 2012
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemoryIndex", "..\..\..\src\contrib\MemoryIndex\MemoryIndex.csproj", "{F8828899-D9DA-4DF9-B22F-58F1DC0059AA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net", "..\..\..\src\core\Lucene.Net.csproj", "{5D4AD9BE-1FFB-41AB-9943-25737971BF57}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F8828899-D9DA-4DF9-B22F-58F1DC0059AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F8828899-D9DA-4DF9-B22F-58F1DC0059AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F8828899-D9DA-4DF9-B22F-58F1DC0059AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F8828899-D9DA-4DF9-B22F-58F1DC0059AA}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5D4AD9BE-1FFB-41AB-9943-25737971BF57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5D4AD9BE-1FFB-41AB-9943-25737971BF57}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5D4AD9BE-1FFB-41AB-9943-25737971BF57}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5D4AD9BE-1FFB-41AB-9943-25737971BF57}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.cs?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.cs (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.cs Mon Mar 26 05:58:26 2012
@@ -0,0 +1,474 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Text;
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Search;
+using Lucene.Net.Support;
+
+namespace Lucene.Net.Index.Memory {
+    
+    /**
+ * High-performance single-document main memory Apache Lucene fulltext search index. 
+ * 
+ * <h4>Overview</h4>
+ * 
+ * This class is a replacement/substitute for a large subset of
+ * {@link RAMDirectory} functionality. It is designed to
+ * enable maximum efficiency for on-the-fly matchmaking combining structured and 
+ * fuzzy fulltext search in realtime streaming applications such as Nux XQuery based XML 
+ * message queues, publish-subscribe systems for Blogs/newsfeeds, text chat, data acquisition and 
+ * distribution systems, application level routers, firewalls, classifiers, etc. 
+ * Rather than targeting fulltext search of infrequent queries over huge persistent 
+ * data archives (historic search), this class targets fulltext search of huge 
+ * numbers of queries over comparatively small transient realtime data (prospective 
+ * search). 
+ * For example as in 
+ * <pre>
+ * float score = search(String text, Query query)
+ * </pre>
+ * <p>
+ * Each instance can hold at most one Lucene "document", with a document containing
+ * zero or more "fields", each field having a name and a fulltext value. The
+ * fulltext value is tokenized (split and transformed) into zero or more index terms 
+ * (aka words) on <code>addField()</code>, according to the policy implemented by an
+ * Analyzer. For example, Lucene analyzers can split on whitespace, normalize to lower case
+ * for case insensitivity, ignore common terms with little discriminatory value such as "he", "in", "and" (stop
+ * words), reduce the terms to their natural linguistic root form such as "fishing"
+ * being reduced to "fish" (stemming), resolve synonyms/inflexions/thesauri 
+ * (upon indexing and/or querying), etc. For details, see
+ * <a target="_blank" href="http://today.java.net/pub/a/today/2003/07/30/LuceneIntro.html">Lucene Analyzer Intro</a>.
+ * <p>
+ * Arbitrary Lucene queries can be run against this class - see <a target="_blank" 
+ * href="../../../../../../../queryparsersyntax.html">Lucene Query Syntax</a>
+ * as well as <a target="_blank" 
+ * href="http://today.java.net/pub/a/today/2003/11/07/QueryParserRules.html">Query Parser Rules</a>.
+ * Note that a Lucene query selects on the field names and associated (indexed) 
+ * tokenized terms, not on the original fulltext(s) - the latter are not stored 
+ * but rather thrown away immediately after tokenization.
+ * <p>
+ * For some interesting background information on search technology, see Bob Wyman's
+ * <a target="_blank" 
+ * href="http://bobwyman.pubsub.com/main/2005/05/mary_hodder_poi.html">Prospective Search</a>, 
+ * Jim Gray's
+ * <a target="_blank" href="http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=293&page=4">
+ * A Call to Arms - Custom subscriptions</a>, and Tim Bray's
+ * <a target="_blank" 
+ * href="http://www.tbray.org/ongoing/When/200x/2003/07/30/OnSearchTOC">On Search, the Series</a>.
+ * 
+ * 
+ * <h4>Example Usage</h4> 
+ * 
+ * <pre>
+ * Analyzer analyzer = PatternAnalyzer.DEFAULT_ANALYZER;
+ * //Analyzer analyzer = new SimpleAnalyzer();
+ * MemoryIndex index = new MemoryIndex();
+ * index.addField("content", "Readings about Salmons and other select Alaska fishing Manuals", analyzer);
+ * index.addField("author", "Tales of James", analyzer);
+ * QueryParser parser = new QueryParser("content", analyzer);
+ * float score = index.search(parser.parse("+author:james +salmon~ +fish* manual~"));
+ * if (score &gt; 0.0f) {
+ *     System.out.println("it's a match");
+ * } else {
+ *     System.out.println("no match found");
+ * }
+ * System.out.println("indexData=" + index.toString());
+ * </pre>
+ * 
+ * 
+ * <h4>Example XQuery Usage</h4> 
+ * 
+ * <pre>
+ * (: An XQuery that finds all books authored by James that have something to do with "salmon fishing manuals", sorted by relevance :)
+ * declare namespace lucene = "java:nux.xom.pool.FullTextUtil";
+ * declare variable $query := "+salmon~ +fish* manual~"; (: any arbitrary Lucene query can go here :)
+ * 
+ * for $book in /books/book[author="James" and lucene:match(abstract, $query) > 0.0]
+ * let $score := lucene:match($book/abstract, $query)
+ * order by $score descending
+ * return $book
+ * </pre>
+ * 
+ * 
+ * <h4>No thread safety guarantees</h4>
+ * 
+ * An instance can be queried multiple times with the same or different queries,
+ * but an instance is not thread-safe. If desired use idioms such as:
+ * <pre>
+ * MemoryIndex index = ...
+ * synchronized (index) {
+ *    // read and/or write index (i.e. add fields and/or query)
+ * } 
+ * </pre>
+ * 
+ * 
+ * <h4>Performance Notes</h4>
+ * 
+ * Internally there's a new data structure geared towards efficient indexing 
+ * and searching, plus the necessary support code to seamlessly plug into the Lucene 
+ * framework.
+ * <p>
+ * This class performs very well for very small texts (e.g. 10 chars) 
+ * as well as for large texts (e.g. 10 MB) and everything in between. 
+ * Typically, it is about 10-100 times faster than <code>RAMDirectory</code>.
+ * Note that <code>RAMDirectory</code> has particularly 
+ * large efficiency overheads for small to medium sized texts, both in time and space.
+ * Indexing a field with N tokens takes O(N) in the best case, and O(N logN) in the worst 
+ * case. Memory consumption is probably larger than for <code>RAMDirectory</code>.
+ * <p>
+ * Example throughput of many simple term queries over a single MemoryIndex: 
+ * ~500000 queries/sec on a MacBook Pro, jdk 1.5.0_06, server VM. 
+ * As always, your mileage may vary.
+ * <p>
+ * If you're curious about
+ * the whereabouts of bottlenecks, run java 1.5 with the non-perturbing '-server
+ * -agentlib:hprof=cpu=samples,depth=10' flags, then study the trace log and
+ * correlate its hotspot trailer with its call stack headers (see <a
+ * target="_blank"
+ * href="http://java.sun.com/developer/technicalArticles/Programming/HPROF.html">
+ * hprof tracing </a>).
+ *
+ */
+    public class MemoryIndex : ISerializable 
+    {
+
+        private static readonly SortedDictionary<String,Info> sortedFields = new SortedDictionary<String,Info>();
+  
+        /** pos: positions[3*i], startOffset: positions[3*i +1], endOffset: positions[3*i +2] */
+        private readonly int stride;
+  
+        /** Could be made configurable; See {@link Document#setBoost(float)} */
+        private const float docBoost = 1.0f;
+  
+        private static long serialVersionUID = 2782195016849084649L;
+
+        private static bool DEBUG = false;
+  
+        #region Constructors
+    
+        /// <summary>
+        /// Constructs and empty instance
+        /// </summary>
+        public MemoryIndex() : this(false) 
+        {}
+
+        /// <summary>
+        /// Constructs an empty instance that can optionally store the start and end
+        /// character offset of each token term in the text. This can be useful for
+        /// highlighting of hit locations with the Lucene highlighter package.
+        /// Private until the highlighter package matures, so that this can actually
+        /// be meaningfully integrated.
+        /// </summary>
+        /// <param>
+        /// storeOffsets: weather or not to store thes start and end character offest of each 
+        /// token temr in the text
+        /// </param>
+        private MemoryIndex(bool storeOffsets) {
+            this.stride = storeOffsets ? 3 : 1;
+        }
+  
+        #endregion
+    
+        /// <summary>
+        /// Convenience method; Creates and returns a token stream that generates a
+        /// token for each keyword in the given collection, "as is", without any
+        /// transforming text analysis. The resulting token stream can be fed into
+        /// {@link #addField(String, TokenStream)}, perhaps wrapped into another
+        /// {@link org.apache.lucene.analysis.TokenFilter}, as desired.
+        /// 
+        /// @param keywords
+        ///            the keywords to generate tokens for
+        /// @return the corresponding token stream
+        /// </summary>
+        public TokenStream KeywordTokenStream<T>(IList<T> keywords) 
+        {
+            if (keywords == null)
+                throw new ArgumentException("keywords must not be null");
+
+            return new MemoryIndexTokenStream(keywords);
+        }
+  
+        /// <summary>
+        /// Convenience method; Tokenizes the given field text and adds the resulting
+        /// terms to the index; Equivalent to adding an indexed non-keyword Lucene
+        /// {@link org.apache.lucene.document.Field} that is
+        /// {@link org.apache.lucene.document.Field.Index#ANALYZED tokenized},
+        /// {@link org.apache.lucene.document.Field.Store#NO not stored},
+        /// {@link org.apache.lucene.document.Field.TermVector#WITH_POSITIONS termVectorStored with positions} (or
+        /// {@link org.apache.lucene.document.Field.TermVector#WITH_POSITIONS termVectorStored with positions and offsets}),
+        /// 
+        /// @param fieldName
+        ///            a name to be associated with the text
+        /// @param text
+        ///            the text to tokenize and index.
+        /// @param analyzer
+        ///            the analyzer to use for tokenization
+        /// </summary>
+        public void AddField(String fieldName, String text, Analyzer analyzer) 
+        {
+            if (fieldName == null)
+                throw new ArgumentException("fieldName must not be null");
+            if (text == null)
+                throw new ArgumentException("text must not be null");
+            if (analyzer == null)
+                throw new ArgumentException("analyzer must not be null");
+    
+            TokenStream stream = analyzer.TokenStream(fieldName, new StringReader(text));
+
+            AddField(fieldName, stream);
+        }
+    
+        /// <summary>
+        /// Equivalent to <code>AddField(fieldName, stream 1.0f)</code>
+        /// </summary>
+        /// <param name="fieldName">A name to be associated with the text</param>
+        /// <param name="stream">The token stream to retrieve tokens from</param>
+        public void AddField(String fieldName, TokenStream stream) {
+            AddField(fieldName, stream, 1.0f);
+        }
+
+        /// <summary>
+        /// Iterate over the given token stream and adds the resulting terms to the index;
+        /// Equivalent to adding a tokenized, indexed, termVectorStored, unstored, Lucene 
+        /// <see>Lucene.Net.Documents.Field</see>. Finally closes the token stream.
+        /// 
+        /// Note: Untokenized keywords can be added with this method via {@link #keywordTokenStream(Collection)}, 
+        /// the Lucene contrib <code>KeywordTokenizer</code> or similar utilities.
+        /// 
+        /// </summary>
+        /// <param name="fieldName">A name to be associated with the text</param>
+        /// <param name="boost">The token stream to retrieve tokens from</param>
+        /// <param name="stream">The boost factor for hits for this field 
+        ///     <seealso>Lucene.Net.Documents.Field#SetBoost</seealso>
+        /// </param>
+        public void AddField(String fieldName, TokenStream stream, float boost) 
+        {
+            try {
+                if (fieldName == null)
+                    throw new ArgumentException("fieldName must not be null");
+        
+                if (stream == null)
+                    throw new ArgumentException("token stream must not be null");
+        
+                if (boost <= 0.0f)
+                    throw new ArgumentException("boost factor must be greater than 0.0");
+        
+                if (sortedFields[fieldName] != null)
+                    throw new ArgumentException("field must not be added more than once");
+      
+                var terms = new Dictionary<String,List<Int32>>();
+                int numTokens = 0;
+                int numOverlapTokens = 0;
+                int pos = -1;
+      
+                var termAtt = stream.AddAttribute<TermAttribute>();
+                var posIncrAttribute = stream.AddAttribute<PositionIncrementAttribute>();
+                var offsetAtt = stream.AddAttribute<OffsetAttribute>();
+
+                stream.Reset();
+                
+                while (stream.IncrementToken())
+                {
+                    var term = termAtt.Term();
+                    if (term.Length == 0) continue; // nothing to do
+
+                    numTokens++;
+                    int posIncr = posIncrAttribute.PositionIncrement;
+
+                    if (posIncr == 0)
+                        numOverlapTokens++;
+
+                    pos += posIncr;
+
+                    List<Int32> positions = terms[term];
+                    if (positions == null) 
+                    { 
+                        positions = new List<Int32>();
+                        terms.Add(term, positions);
+                    }
+
+                    if (stride == 1) 
+                    {
+                        positions.Add(pos);
+                    } 
+                    else 
+                    {
+                        positions.Insert(offsetAtt.StartOffset, pos);
+                    }
+                }
+            
+                stream.End();
+
+                // ensure infos.numTokens > 0 invariant; needed for correct operation of terms()
+                if (numTokens > 0) 
+                {
+                    boost = boost * docBoost; // see DocumentWriter.addDocument(...)
+                    sortedFields.Add(fieldName, new Info(terms, numTokens, numOverlapTokens, boost));
+                    sortedFields = null;    // invalidate sorted view, if any
+                }
+            } finally {
+                try {
+                    if (stream != null) stream.Dispose();
+                } catch (IOException e2) {
+                    throw new SystemException("Error Disposing of Stream", e2);
+                }
+            }
+        }
+  
+        /// <summary>
+        /// Creates and returns a searcher that can be used to execute arbitrary
+        /// Lucene queries and to collect the resulting query results as hits.
+        /// </summary>
+        /// <returns>A searcher</returns>
+        public IndexSearcher CreateSearcher() {
+            MemoryIndexReader reader = new MemoryIndexReader();
+            var searcher = new IndexSearcher(reader); // ensures no auto-close !!
+            reader.SetSearcher(searcher); // to later get hold of searcher.getSimilarity()
+            return searcher;
+        }
+  
+        /**
+       * Convenience method that efficiently returns the relevance score by
+       * matching this index against the given Lucene query expression.
+       * 
+       * @param query
+       *            an arbitrary Lucene query to run against this index
+       * @return the relevance score of the matchmaking; A number in the range
+       *         [0.0 .. 1.0], with 0.0 indicating no match. The higher the number
+       *         the better the match.
+       *
+       */
+        public float Search(Query query) 
+        {
+            if (query == null) 
+                throw new ArgumentException("query must not be null");
+    
+            Searcher searcher = createSearcher();
+            
+            List<float> scores = new List<float>(); // inits to 0.0f (no match)
+            searcher.Search(query, new AnonCollector());
+            float score = scores[0];
+            return score;
+        }
+  
+        /// <summary>
+        /// Returns a reasonable approximation of the main memory [bytes] consumed by
+        /// this instance. Useful for smart memory sensititive caches/pools. Assumes
+        /// fieldNames are interned, whereas tokenized terms are memory-overlaid.
+        /// </summary>
+        public int GetMemorySize()
+        {
+            return Marshal.SizeOf(this);
+        } 
+
+        private int NumPositions(ICollection<int> positions) {
+            return positions.Count / stride;
+        }
+  
+        /**
+        * Returns a String representation of the index data for debugging purposes.
+        * 
+        * @return the string representation
+        */
+        public override String ToString() {
+            var result = new StringBuilder(256);    
+            int sumChars = 0;
+            int sumPositions = 0;
+            int sumTerms = 0;
+
+            foreach (var sortedField in sortedFields)
+            {
+                result.Append(sortedField.Key + ":\n");
+
+                int numChars = 0;
+                int numPositions = 0;
+
+                foreach (var field in sortedField.Value.SortedTerms)
+                {
+                    result.Append("\t'" + field.Key + "':" + NumPositions(field.Value) + ":");
+                    result.Append(field.Value.ToString()); 
+                    result.Append("\n");
+                    numPositions += NumPositions(field.Value);
+                    numChars += field.Key.Length;
+                }
+
+                result.Append("\tterms=" + sortedField.Value.SortedTerms.Count);
+                result.Append(", positions=" + numPositions);
+                result.Append(", Kchars=" + (numChars/1000.0f));
+                result.Append("\n");
+                sumPositions += numPositions;
+                sumChars += numChars;
+                sumTerms += sortedField.Value.SortedTerms.Count;
+            
+            }
+    
+            result.Append("\nfields=" + sortedFields.Count);
+            result.Append(", terms=" + sumTerms);
+            result.Append(", positions=" + sumPositions);
+            result.Append(", Kchars=" + (sumChars/1000.0f));
+
+            return result.ToString();
+        }
+   
+
+        #region Implementation of ISerializable
+
+        /// <summary>
+        /// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data. </param><param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization. </param><exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
+        public void GetObjectData(SerializationInfo info, StreamingContext context)
+        {
+            throw new NotImplementedException();
+        }
+
+        #endregion
+    }
+   
+    internal class AnonCollector : Collector
+    {
+        private Scorer _scorer;
+
+        #region Overrides of Collector
+
+        public override void SetScorer(Scorer scorer)
+        {
+            _scorer = scorer;
+        }
+
+        public override void Collect(int doc)
+        {
+            scorer[0] = _scorer.Score();
+        }
+
+        public override void SetNextReader(IndexReader reader, int docBase) {}
+
+        public override bool AcceptsDocsOutOfOrder
+        {
+            get { return true; }
+        }
+
+        #endregion
+    }
+ 
+}

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.csproj
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.csproj?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.csproj (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndex.csproj Mon Mar 26 05:58:26 2012
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{F8828899-D9DA-4DF9-B22F-58F1DC0059AA}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MemoryIndex</RootNamespace>
+    <AssemblyName>MemoryIndex</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="MemoryIndex.cs" />
+    <Compile Include="MemoryIndexReader.cs" />
+    <Compile Include="MemoryIndexTokenStream.cs" />
+    <Compile Include="MemoryInfo.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="VM.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\core\Lucene.Net.csproj">
+      <Project>{5D4AD9BE-1FFB-41AB-9943-25737971BF57}</Project>
+      <Name>Lucene.Net</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexReader.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexReader.cs?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexReader.cs (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexReader.cs Mon Mar 26 05:58:26 2012
@@ -0,0 +1,487 @@
+using System;
+using Lucene.Net.Search;
+
+namespace Lucene.Net.Index.Memory
+{
+    private static final Term MATCH_ALL_TERM = new Term("");
+    
+    /**
+    * Search support for Lucene framework integration; implements all methods
+    * required by the Lucene IndexReader contracts.
+    */
+    internal class MemoryIndexReader : IndexReader {
+    
+        private Searcher searcher; // needed to find searcher.getSimilarity() 
+    
+        private MemoryIndexReader() {}
+    
+        private Info getInfo(String fieldName) 
+        {
+            return fields.get(fieldName);
+        }
+        
+        private Info getInfo(int pos) 
+        {
+            return sortedFields[pos].getValue();
+        }
+    
+        public override int docFreq(Term term) 
+        {
+            Info info = getInfo(term.field());
+            int freq = 0;
+            if (info != null) freq = info.getPositions(term.text()) != null ? 1 : 0;
+            if (DEBUG) System.err.println("MemoryIndexReader.docFreq: " + term + ", freq:" + freq);
+            return freq;
+        }
+  
+        public TermEnum terms() 
+        {
+            if (DEBUG) System.err.println("MemoryIndexReader.terms()");
+            return terms(MATCH_ALL_TERM);
+        }
+    
+        public TermEnum terms(Term term) 
+        {
+            if (DEBUG) System.err.println("MemoryIndexReader.terms: " + term);
+  
+            int i; // index into info.sortedTerms
+            int j; // index into sortedFields
+      
+            sortFields();
+            if (sortedFields.length == 1 && sortedFields[0].getKey() == term.field()) {
+                j = 0; // fast path
+            } else {
+                j = Arrays.binarySearch(sortedFields, term.field(), termComparator);
+            }
+      
+            if (j < 0) { // not found; choose successor
+                j = -j -1; 
+                i = 0;
+                if (j < sortedFields.length) 
+                    getInfo(j).sortTerms();
+            } else { // found
+                Info info = getInfo(j);
+                info.sortTerms();
+                i = Arrays.binarySearch(info.sortedTerms, term.text(), termComparator);
+                if (i < 0) { // not found; choose successor
+                    i = -i -1;
+                
+                    if (i >= info.sortedTerms.length) { // move to next successor
+                        j++;
+                        i = 0;
+                        if (j < sortedFields.length) getInfo(j).sortTerms();
+                    }
+                }
+            }
+    
+            final int ix = i;
+            final int jx = j;
+  
+    return new TermEnum() {
+  
+    }
+  
+    @Override
+    public TermPositions termPositions() {
+    if (DEBUG) System.err.println("MemoryIndexReader.termPositions");
+      
+    return new TermPositions() {
+  
+    private boolean hasNext;
+    private int cursor = 0;
+    private List<Int32> current;
+    private Term term;
+        
+    public void seek(Term term) {
+    this.term = term;
+    if (DEBUG) System.err.println(".seek: " + term);
+    if (term == null) {
+    hasNext = true;  // term==null means match all docs
+    } else {
+    Info info = getInfo(term.field());
+    current = info == null ? null : info.getPositions(term.text());
+    hasNext = (current != null);
+    cursor = 0;
+    }
+    }
+  
+    public void seek(TermEnum termEnum) {
+    if (DEBUG) System.err.println(".seekEnum");
+    seek(termEnum.term());
+    }
+  
+    public int doc() {
+    if (DEBUG) System.err.println(".doc");
+    return 0;
+    }
+  
+    public int freq() {
+    int freq = current != null ? numPositions(current) : (term == null ? 1 : 0);
+    if (DEBUG) System.err.println(".freq: " + freq);
+    return freq;
+    }
+  
+    public boolean next() {
+    if (DEBUG) System.err.println(".next: " + current + ", oldHasNext=" + hasNext);
+    boolean next = hasNext;
+    hasNext = false;
+    return next;
+    }
+  
+    public int read(int[] docs, int[] freqs) {
+    if (DEBUG) System.err.println(".read: " + docs.length);
+    if (!hasNext) return 0;
+    hasNext = false;
+    docs[0] = 0;
+    freqs[0] = freq();
+    return 1;
+    }
+  
+    public boolean skipTo(int target) {
+    if (DEBUG) System.err.println(".skipTo: " + target);
+    return next();
+    }
+  
+    public void close() {
+    if (DEBUG) System.err.println(".close");
+    }
+        
+    public int nextPosition() { // implements TermPositions
+    int pos = current.get(cursor);
+    cursor += stride;
+    if (DEBUG) System.err.println(".nextPosition: " + pos);
+    return pos;
+    }
+        
+    /**
+         * Not implemented.
+         * @throws UnsupportedOperationException
+         */
+    public int getPayloadLength() {
+    throw new UnsupportedOperationException();
+    }
+         
+    /**
+         * Not implemented.
+         * @throws UnsupportedOperationException
+         */
+    public byte[] getPayload(byte[] data, int offset) throws IOException {
+    throw new UnsupportedOperationException();
+    }
+
+    public boolean isPayloadAvailable() {
+    // unsuported
+    return false;
+    }
+
+    };
+    }
+  
+    @Override
+    public TermDocs termDocs() {
+    if (DEBUG) System.err.println("MemoryIndexReader.termDocs");
+    return termPositions();
+    }
+  
+    @Override
+    public TermFreqVector[] getTermFreqVectors(int docNumber) {
+    if (DEBUG) System.err.println("MemoryIndexReader.getTermFreqVectors");
+    TermFreqVector[] vectors = new TermFreqVector[fields.size()];
+    //      if (vectors.length == 0) return null;
+    Iterator<String> iter = fields.keySet().iterator();
+    for (int i=0; i < vectors.length; i++) {
+    vectors[i] = getTermFreqVector(docNumber, iter.next());
+    }
+    return vectors;
+    }
+
+    @Override
+    public void getTermFreqVector(int docNumber, TermVectorMapper mapper) throws IOException
+    {
+    if (DEBUG) System.err.println("MemoryIndexReader.getTermFreqVectors");
+
+    //      if (vectors.length == 0) return null;
+    for (final String fieldName : fields.keySet())
+    {
+    getTermFreqVector(docNumber, fieldName, mapper);
+    }
+    }
+
+    @Override
+    public void getTermFreqVector(int docNumber, String field, TermVectorMapper mapper) throws IOException
+    {
+    if (DEBUG) System.err.println("MemoryIndexReader.getTermFreqVector");
+    final Info info = getInfo(field);
+    if (info == null){
+    return;
+    }
+    info.sortTerms();
+    mapper.setExpectations(field, info.sortedTerms.length, stride != 1, true);
+    for (int i = info.sortedTerms.length; --i >=0;){
+
+    List<Int32> positions = info.sortedTerms[i].getValue();
+    int size = positions.size();
+    org.apache.lucene.index.TermVectorOffsetInfo[] offsets =
+    new org.apache.lucene.index.TermVectorOffsetInfo[size / stride];
+
+    for (int k=0, j=1; j < size; k++, j += stride) {
+    int start = positions.get(j);
+    int end = positions.get(j+1);
+    offsets[k] = new org.apache.lucene.index.TermVectorOffsetInfo(start, end);
+    }
+    mapper.map(info.sortedTerms[i].getKey(),
+    numPositions(info.sortedTerms[i].getValue()),
+    offsets, (info.sortedTerms[i].getValue()).toArray(stride));
+    }
+    }
+
+    @Override
+    public TermFreqVector getTermFreqVector(int docNumber, final String fieldName) {
+    if (DEBUG) System.err.println("MemoryIndexReader.getTermFreqVector");
+    final Info info = getInfo(fieldName);
+    if (info == null) return null; // TODO: or return empty vector impl???
+    info.sortTerms();
+      
+    return new TermPositionVector() { 
+  
+    private final Map.Entry<String,List<Int32>>[] sortedTerms = info.sortedTerms;
+        
+    public String getField() {
+    return fieldName;
+    }
+  
+    public int size() {
+    return sortedTerms.length;
+    }
+  
+    public String[] getTerms() {
+    String[] terms = new String[sortedTerms.length];
+    for (int i=sortedTerms.length; --i >= 0; ) {
+    terms[i] = sortedTerms[i].getKey();
+    }
+    return terms;
+    }
+  
+    public int[] getTermFrequencies() {
+    int[] freqs = new int[sortedTerms.length];
+    for (int i=sortedTerms.length; --i >= 0; ) {
+    freqs[i] = numPositions(sortedTerms[i].getValue());
+    }
+    return freqs;
+    }
+  
+    public int indexOf(String term) {
+    int i = Arrays.binarySearch(sortedTerms, term, termComparator);
+    return i >= 0 ? i : -1;
+    }
+  
+    public int[] indexesOf(String[] terms, int start, int len) {
+    int[] indexes = new int[len];
+    for (int i=0; i < len; i++) {
+    indexes[i] = indexOf(terms[start++]);
+    }
+    return indexes;
+    }
+        
+    // lucene >= 1.4.3
+    public int[] getTermPositions(int index) {
+    return sortedTerms[index].getValue().toArray(stride);
+    } 
+        
+    // lucene >= 1.9 (remove this method for lucene-1.4.3)
+    public org.apache.lucene.index.TermVectorOffsetInfo[] getOffsets(int index) {
+    if (stride == 1) return null; // no offsets stored
+          
+    List<Int32> positions = sortedTerms[index].getValue();
+    int size = positions.size();
+    org.apache.lucene.index.TermVectorOffsetInfo[] offsets = 
+    new org.apache.lucene.index.TermVectorOffsetInfo[size / stride];
+          
+    for (int i=0, j=1; j < size; i++, j += stride) {
+    int start = positions.get(j);
+    int end = positions.get(j+1);
+    offsets[i] = new org.apache.lucene.index.TermVectorOffsetInfo(start, end);
+    }
+    return offsets;
+    }
+
+    };
+    }
+
+    private Similarity getSimilarity() {
+    if (searcher != null) return searcher.getSimilarity();
+    return Similarity.getDefault();
+    }
+    
+    private void setSearcher(Searcher searcher) {
+    this.searcher = searcher;
+    }
+    
+    /** performance hack: cache norms to avoid repeated expensive calculations */
+    private byte[] cachedNorms;
+    private String cachedFieldName;
+    private Similarity cachedSimilarity;
+    
+    @Override
+    public byte[] norms(String fieldName) {
+    byte[] norms = cachedNorms;
+    Similarity sim = getSimilarity();
+    if (fieldName != cachedFieldName || sim != cachedSimilarity) { // not cached?
+    Info info = getInfo(fieldName);
+    int numTokens = info != null ? info.numTokens : 0;
+    int numOverlapTokens = info != null ? info.numOverlapTokens : 0;
+    float boost = info != null ? info.getBoost() : 1.0f; 
+    FieldInvertState invertState = new FieldInvertState(0, numTokens, numOverlapTokens, 0, boost);
+    float n = sim.computeNorm(fieldName, invertState);
+    byte norm = Similarity.encodeNorm(n);
+    norms = new byte[] {norm};
+        
+    // cache it for future reuse
+    cachedNorms = norms;
+    cachedFieldName = fieldName;
+    cachedSimilarity = sim;
+    if (DEBUG) System.err.println("MemoryIndexReader.norms: " + fieldName + ":" + n + ":" + norm + ":" + numTokens);
+    }
+    return norms;
+    }
+  
+    @Override
+    public void norms(String fieldName, byte[] bytes, int offset) {
+    if (DEBUG) System.err.println("MemoryIndexReader.norms*: " + fieldName);
+    byte[] norms = norms(fieldName);
+    System.arraycopy(norms, 0, bytes, offset, norms.length);
+    }
+  
+    @Override
+    protected void doSetNorm(int doc, String fieldName, byte value) {
+    throw new UnsupportedOperationException();
+    }
+  
+    @Override
+    public int numDocs() {
+    if (DEBUG) System.err.println("MemoryIndexReader.numDocs");
+    return fields.size() > 0 ? 1 : 0;
+    }
+  
+    @Override
+    public int maxDoc() {
+    if (DEBUG) System.err.println("MemoryIndexReader.maxDoc");
+    return 1;
+    }
+  
+    @Override
+    public Document document(int n) {
+    if (DEBUG) System.err.println("MemoryIndexReader.document");
+    return new Document(); // there are no stored fields
+    }
+
+    //When we convert to JDK 1.5 make this Set<String>
+    @Override
+    public Document document(int n, FieldSelector fieldSelector) throws IOException {
+    if (DEBUG) System.err.println("MemoryIndexReader.document");
+    return new Document(); // there are no stored fields
+    }
+
+    @Override
+    public boolean isDeleted(int n) {
+    if (DEBUG) System.err.println("MemoryIndexReader.isDeleted");
+    return false;
+    }
+  
+    @Override
+    public boolean hasDeletions() {
+    if (DEBUG) System.err.println("MemoryIndexReader.hasDeletions");
+    return false;
+    }
+  
+    @Override
+    protected void doDelete(int docNum) {
+    throw new UnsupportedOperationException();
+    }
+  
+    @Override
+    protected void doUndeleteAll() {
+    throw new UnsupportedOperationException();
+    }
+  
+    @Override
+    protected void doCommit(Map<String,String> commitUserData) {
+    if (DEBUG) System.err.println("MemoryIndexReader.doCommit");
+    }
+  
+    @Override
+    protected void doClose() {
+    if (DEBUG) System.err.println("MemoryIndexReader.doClose");
+    }
+    
+    // lucene >= 1.9 (remove this method for lucene-1.4.3)
+    public override Collection<String> getFieldNames(FieldOption fieldOption) {
+        if (DEBUG) 
+            System.err.println("MemoryIndexReader.getFieldNamesOption");
+        
+        if (fieldOption == FieldOption.UNINDEXED) 
+            return Collections.<String>emptySet();
+        
+        if (fieldOption == FieldOption.INDEXED_NO_TERMVECTOR) 
+            return Collections.<String>emptySet();
+    
+        if (fieldOption == FieldOption.TERMVECTOR_WITH_OFFSET && stride == 1) 
+            return Collections.<String>emptySet();
+    
+        if (fieldOption == FieldOption.TERMVECTOR_WITH_POSITION_OFFSET && stride == 1) 
+            return Collections.<String>emptySet();
+      
+        return Collections.unmodifiableSet(fields.keySet());
+    }
+    }
+
+ private class AnonTermEnum : TermEnum
+ {
+    private int i = ix; // index into info.sortedTerms
+    private int j = jx; // index into sortedFields
+          
+    public override bool Next() {
+        if (DEBUG) System.err.println("TermEnum.next");
+        if (j >= sortedFields.length) return false;
+         Info info = getInfo(j);
+            if (++i < info.sortedTerms.length) return true;
+  
+        // move to successor
+        j++;
+        i = 0;
+        if (j >= sortedFields.length) return false;
+        getInfo(j).sortTerms();
+        return true;
+    }
+  
+    public override Term Term() {
+        if (DEBUG) System.err.println("TermEnum.term: " + i);
+        if (j >= sortedFields.length) return null;
+        Info info = getInfo(j);
+        if (i >= info.sortedTerms.length) return null;
+        //          if (DEBUG) System.err.println("TermEnum.term: " + i + ", " + info.sortedTerms[i].getKey());
+        return createTerm(info, j, info.sortedTerms[i].getKey());
+    }
+        
+    public override int DocFreq() {
+        if (DEBUG) System.err.println("TermEnum.docFreq");
+        if (j >= sortedFields.length) return 0;
+        Info info = getInfo(j);
+        if (i >= info.sortedTerms.length) return 0;
+        return numPositions(info.getPositions(i));
+    }
+  
+    /** Returns a new Term object, minimizing String.intern() overheads. */
+    private Term CreateTerm(Info info, int pos, String text) { 
+        // Assertion: sortFields has already been called before
+        Term template = info.template;
+        if (template == null) { // not yet cached?
+        String fieldName = sortedFields[pos].getKey();
+        template = new Term(fieldName);
+        info.template = template;
+    }
+          
+    return template.createTerm(text);
+       
+ }
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexTokenStream.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexTokenStream.cs?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexTokenStream.cs (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryIndexTokenStream.cs Mon Mar 26 05:58:26 2012
@@ -0,0 +1,47 @@
+
+using System;
+using System.Collections.Generic;
+using Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+
+namespace Lucene.Net.Index.Memory
+{
+    class MemoryIndexTokenStream : TokenStream
+    {
+        private IList<T> _keywords;
+        private int start = 0;
+        private TermAttribute termAtt = AddAttribute(TermAttribute.class);
+        private OffsetAttribute offsetAtt = AddAttribute(OffsetAttribute.class);
+      
+        public MemoryIndexTokenStream(IList<T> keywords)
+        {
+            _keywords = keywords;
+        }
+
+        public override bool IncrementToken()
+        {
+            if (iter.hasNext()) return false;
+        
+            Object obj = iter.Next();
+
+            if (obj == null) 
+                throw new ArgumentException("keyword must not be null");
+        
+            String term = obj.ToString();
+            ClearAttributes();
+            termAtt.SetTermBuffer(term);
+            offsetAtt.SetOffset(start, start+termAtt.TermLength());
+            start += term.Length + 1; // separate words by 1 (blank) character
+            
+            return true;
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            // do nothing
+        }
+    }
+}
+
+        
+     
\ No newline at end of file

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryInfo.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryInfo.cs?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryInfo.cs (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/MemoryInfo.cs Mon Mar 26 05:58:26 2012
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace Lucene.Net.Index.Memory
+{
+    /// <summary>
+    /// Index data structure for a field; Contains the tokenized term texts
+    /// and their positions
+    /// </summary>
+    internal class Info : ISerializable {
+    
+        /**
+         * Term strings and their positions for this field: Map <String
+         * termText, List<Int32> positions>
+         */
+        public SortedDictionary<String, List<Int32>> SortedTerms { get; private set; }
+        
+        /** Number of added tokens for this field */
+        private int numTokens;
+    
+        /** Number of overlapping tokens for this field */
+        private int numOverlapTokens;
+    
+        /** Boost factor for hits for this field */
+        public float Boost { get; private set; }
+
+        /** Term for this field's fieldName, lazily computed on demand */
+        public Term template;
+
+        private long serialVersionUID = 2882195016849084649L;  
+
+        public Info(IDictionary<string, List<int>> terms, int numTokens, int numOverlapTokens, float boost) {
+            SortedTerms = new SortedDictionary<string, List<int>>(terms);
+            Boost = boost;
+        
+            this.numTokens = numTokens;
+            this.numOverlapTokens = numOverlapTokens;
+        }
+    
+        public List<Int32> GetPositions(string pos)
+        {
+            return SortedTerms[pos];
+        }
+
+        public List<Int32> GetPositions(int pos) {
+            return SortedTerms.ElementAt(pos).Value;
+        }
+
+        #region Implementation of ISerializable
+
+        /// <summary>
+        /// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data. </param><param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization. </param><exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
+        public void GetObjectData(SerializationInfo info, StreamingContext context)
+        {
+            throw new NotImplementedException();
+        }
+
+        #endregion
+    }
+}

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/Properties/AssemblyInfo.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/Properties/AssemblyInfo.cs?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/Properties/AssemblyInfo.cs (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/Properties/AssemblyInfo.cs Mon Mar 26 05:58:26 2012
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MemoryIndex")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MemoryIndex")]
+[assembly: AssemblyCopyright("Copyright ©  2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7df01e88-2ca5-407e-8eed-5b51d4988718")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

Added: incubator/lucene.net/trunk/src/contrib/MemoryIndex/VM.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/src/contrib/MemoryIndex/VM.cs?rev=1305232&view=auto
==============================================================================
--- incubator/lucene.net/trunk/src/contrib/MemoryIndex/VM.cs (added)
+++ incubator/lucene.net/trunk/src/contrib/MemoryIndex/VM.cs Mon Mar 26 05:58:26 2012
@@ -0,0 +1,91 @@
+using System;
+
+namespace Lucene.Net.Index.Memory
+{
+
+    /// <summary>
+    /// I think this approximation can be replaced by MashalBy.SizeOf(obj);
+    /// </summary>
+    internal class VM
+    {
+        public static int PTR =  Environment.Is64BitProcess ? 8 : 4;    
+
+        // bytes occupied by primitive data types
+        public static int BOOLEAN = 1;
+        public static int BYTE = 1;
+        public static int CHAR = 2;
+        public static int SHORT = 2;
+        public static int INT = 4;
+        public static int LONG = 8;
+        public static int FLOAT = 4;
+        public static int DOUBLE = 8;
+    
+        private static readonly int LOG_PTR = (int) Math.Round(log2(PTR));
+    
+        /**
+        * Object header of any heap allocated Java object. 
+        * ptr to class, info for monitor, gc, hash, etc.
+        */
+        private static readonly int OBJECT_HEADER = 2*PTR; 
+
+        private VM() {} // not instantiable
+
+        //  assumes n > 0
+        //  64 bit VM:
+        //    0     --> 0*PTR
+        //    1..8  --> 1*PTR
+        //    9..16 --> 2*PTR
+        private static int SizeOf(int n) 
+        {
+            return (((n-1) >> LOG_PTR) + 1) << LOG_PTR;
+        }
+    
+        public static int SizeOfObject(int n)
+        {
+            return SizeOf(OBJECT_HEADER + n);        
+        }
+    
+        public static int SizeOfObjectArray(int len) 
+        {
+            return SizeOfObject(INT + PTR*len);        
+        }
+    
+        public static int SizeOfCharArray(int len) 
+        {
+            return SizeOfObject(INT + CHAR*len);        
+        }
+    
+        public static int SizeOfIntArray(int len) 
+        {
+            return SizeOfObject(INT + INT*len);        
+        }
+    
+        public static int SizeOfString(int len) 
+        {
+            return SizeOfObject(3*INT + PTR) + SizeOfCharArray(len);
+        }
+    
+        public static int SizeOfHashMap(int len) 
+        {
+            return SizeOfObject(4*PTR + 4*INT) + SizeOfObjectArray(len) 
+                    + len * SizeOfObject(3*PTR + INT); // entries
+        }
+    
+        // Note: does not include referenced objects
+        public static int SizeOfArrayList(int len) 
+        {
+            return SizeOfObject(PTR + 2*INT) + SizeOfObjectArray(len); 
+        }
+    
+        public static int sizeOfArrayIntList(int len) 
+        {
+            return SizeOfObject(PTR + INT) + SizeOfIntArray(len);
+        }
+    
+        /** logarithm to the base 2. Example: log2(4) == 2, log2(8) == 3 */
+        private static double log2(double value) {
+            return Math.Log(value) / Math.Log(2);
+        }
+        
+    }
+}



Mime
View raw message