Permalink
Browse files

Better way to handle sharing the index searcher instance

  • Loading branch information...
1 parent 56e7062 commit 11c11231680f0f9797d6322814c9acf1ae6b08b7 @ayende ayende committed Aug 7, 2011
@@ -140,10 +140,18 @@ public void Initialize()
private int GetDefaultMemoryCacheLimitMegabytes()
{
- // we need to leave ( a lot ) of room for other things as well, so we limit the cache size
- return (int)(MemoryCache.Default.CacheMemoryLimit / 2 -
+ var totalPhysicalMemoryMegabytes =
+ (int) (new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory/1024/1024);
@Yitzchok
Yitzchok Sep 6, 2011

Microsoft.VisualBasic.Devices.ComputerInfo.TotalPhysicalMemory() isn't implemented on mono :(.

@Yitzchok
Yitzchok Sep 6, 2011

This seems to work for me

        int totalPhysicalMemoryMegabytes;
        if (Type.GetType("Mono.Runtime") != null)
            totalPhysicalMemoryMegabytes = 
                (int)(new PerformanceCounter("Mono Memory", "Total Physical Memory").RawValue / 1024 / 1024);
        else
            totalPhysicalMemoryMegabytes =
            (int)(new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory / 1024 / 1024);
@Yitzchok
Yitzchok Sep 8, 2011

Using PInvoke just makes things harder when you want the application to work on more then one platform (Windows, Linux).
I wouldn't say PInvoke is more straight forward then using some VB namespace (though referencing Microsoft.VisualBasic does mean that you have to install mono-basic on linux).

+ // we need to leave ( a lot ) of room for other things as well, so we limit the cache size
+
+ var val = (totalPhysicalMemoryMegabytes / 2) -
// reduce the unmanaged cache size from the default limit
- (GetConfigurationValue<int>("Raven/Esent/CacheSizeMax") ?? 1024));
+ (GetConfigurationValue<int>("Raven/Esent/CacheSizeMax") ?? 1024);
+
+ if (val < 0)
+ return 128; // if machine has less than 1024 MB, then only use 128 MB
+
+ return val;
}
public NameValueCollection Settings { get; set; }
@@ -52,7 +52,7 @@ public abstract class Index : IDisposable
private readonly object writeLock = new object();
private volatile bool disposed;
private IndexWriter indexWriter;
- private volatile IndexSearcher searcher;
+ private volatile IndexSearcherHolder currentIndexSearcherHolder;
protected Index(Directory directory, string name, IndexDefinition indexDefinition, AbstractViewGenerator viewGenerator)
@@ -79,26 +79,10 @@ protected Index(Directory directory, string name, IndexDefinition indexDefinitio
/// </summary>
public abstract bool IsMapReduce { get; }
- /// <summary>
- /// if you are calling this method, you _have_ to call
- /// searcher.GetIndexReader().DecRef();
- /// when you are done searching
- /// </summary>
- internal IndexSearcher GetSearcher()
- {
- while (true)
- {
- try
- {
- var indexSearcher = searcher;
- indexSearcher.GetIndexReader().IncRef();
- return indexSearcher;
- }
- catch (AlreadyClosedException)
- {
- }
- }
- }
+ internal IDisposable GetSearcher(out IndexSearcher searcher)
+ {
+ return currentIndexSearcherHolder.GetSearcher(out searcher);
+ }
#region IDisposable Members
@@ -111,12 +95,10 @@ public void Dispose()
{
indexExtension.Value.Dispose();
}
- var indexReader = searcher.GetIndexReader();
- searcher.Close();
- while (indexReader.GetRefCount() > 0)
- {
- indexReader.Close();
- }
+ if(currentIndexSearcherHolder != null)
+ {
+ currentIndexSearcherHolder.DisposeRudely();
+ }
if (indexWriter != null)
{
IndexWriter writer = indexWriter;
@@ -415,23 +397,25 @@ public static string TryGetDocKey(object current)
private void RecreateSearcher()
{
- var oldSearcher = searcher;
+ var oldSearcher = currentIndexSearcherHolder;
if (indexWriter == null)
{
- searcher = new IndexSearcher(directory, true);
+ currentIndexSearcherHolder = new IndexSearcherHolder(new IndexSearcher(directory, true));
}
else
{
var indexReader = indexWriter.GetReader();
- searcher = new IndexSearcher(indexReader);
+ currentIndexSearcherHolder = new IndexSearcherHolder(new IndexSearcher(indexReader));
}
if (oldSearcher != null)
{
- var indexReader = oldSearcher.GetIndexReader();
- oldSearcher.Close();
- indexReader.DecRef();
+ IndexSearcher _;
+ using(oldSearcher.GetSearcher(out _))
+ {
+ oldSearcher.DisposeSafely();
+ }
}
}
@@ -547,10 +531,10 @@ public IEnumerable<IndexQueryResult> Query()
using(IndexStorage.EnsureInvariantCulture())
{
AssertQueryDoesNotContainFieldsThatAreNotIndexes();
- var indexSearcher = parent.GetSearcher();
- try
+ IndexSearcher indexSearcher;
+ using(parent.GetSearcher(out indexSearcher))
{
- Query luceneQuery = GetLuceneQuery();
+ var luceneQuery = GetLuceneQuery();
int start = indexQuery.Start;
int pageSize = indexQuery.PageSize;
int returnedResults = 0;
@@ -588,10 +572,6 @@ public IEnumerable<IndexQueryResult> Query()
}
} while (skippedResultsInCurrentLoop > 0 && returnedResults < indexQuery.PageSize);
}
- finally
- {
- indexSearcher.GetIndexReader().DecRef();
- }
}
}
@@ -0,0 +1,48 @@
+using System;
+using System.Threading;
+using Lucene.Net.Search;
+using Raven.Abstractions.Extensions;
+
+namespace Raven.Database.Indexing
+{
+ public class IndexSearcherHolder
+ {
+ private readonly IndexSearcher currentIndexSearcher;
+
+ private volatile bool shouldDispose;
+ private int usage;
+
+ public IndexSearcherHolder(IndexSearcher currentIndexSearcher)
+ {
+ this.currentIndexSearcher = currentIndexSearcher;
+ }
+
+ public IDisposable GetSearcher(out IndexSearcher searcher)
+ {
+ Interlocked.Increment(ref usage);
+ searcher = currentIndexSearcher;
+ return new DisposableAction(TryDispose);
+ }
+
+ public void DisposeSafely()
+ {
+ shouldDispose = true;
+ }
+
+ private void TryDispose()
+ {
+ if (Interlocked.Decrement(ref usage) > 0)
+ return;
+ if (shouldDispose == false)
+ return;
+
+ DisposeRudely();
+ }
+
+ public void DisposeRudely()
+ {
+ currentIndexSearcher.GetIndexReader().Close();
+ currentIndexSearcher.Close();
+ }
+ }
+}
@@ -274,9 +274,9 @@ public void RemoveFromIndex(string index, string[] keys, WorkContext context)
/// searcher.GetIndexReader().DecRef();
/// when you are done searching
/// </summary>
- internal IndexSearcher GetCurrentIndexSearcher(string indexName)
+ internal IDisposable GetCurrentIndexSearcher(string indexName, out IndexSearcher searcher)
{
- return GetIndexByName(indexName).GetSearcher();
+ return GetIndexByName(indexName).GetSearcher(out searcher);
}
private Index GetIndexByName(string indexName)
@@ -39,8 +39,8 @@ public SuggestionQueryResult ExecuteSuggestionQuery(string indexName, Suggestion
return indexExtension.Query(suggestionQuery);
- var currentSearcher = _database.IndexStorage.GetCurrentIndexSearcher(indexName);
- try
+ IndexSearcher currentSearcher;
+ using(_database.IndexStorage.GetCurrentIndexSearcher(indexName,out currentSearcher))
{
var indexReader = currentSearcher.GetIndexReader();
@@ -51,11 +51,6 @@ public SuggestionQueryResult ExecuteSuggestionQuery(string indexName, Suggestion
return suggestionQueryIndexExtension.Query(suggestionQuery);
}
- finally
- {
- currentSearcher.GetIndexReader().DecRef();
- }
-
}
private static StringDistance GetStringDistance(SuggestionQuery query)
@@ -26,8 +26,8 @@ public ISet<string> GetTerms(string index, string field, string fromValue, int p
if(index == null) throw new ArgumentNullException("index");
var result = new HashSet<string>();
- var currentIndexSearcher = database.IndexStorage.GetCurrentIndexSearcher(index);
- try
+ IndexSearcher currentIndexSearcher;
+ using(database.IndexStorage.GetCurrentIndexSearcher(index, out currentIndexSearcher))
{
var termEnum = currentIndexSearcher.GetIndexReader().Terms(new Term(field, fromValue ?? string.Empty));
try
@@ -58,10 +58,6 @@ public ISet<string> GetTerms(string index, string field, string fromValue, int p
termEnum.Close();
}
}
- finally
- {
- currentIndexSearcher.GetIndexReader().DecRef();
- }
return result;
}
@@ -69,6 +69,7 @@
<HintPath>..\SharedLibs\Lucene.Net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
+ <Reference Include="Microsoft.VisualBasic" />
<Reference Include="Newtonsoft.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\SharedLibs\Newtonsoft.Json.dll</HintPath>
@@ -126,6 +127,7 @@
<Compile Include="Indexing\ErrorLoggingConcurrentMergeScheduler.cs" />
<Compile Include="Indexing\FieldsToFetch.cs" />
<Compile Include="Indexing\IIndexExtension.cs" />
+ <Compile Include="Indexing\IndexSearcherHolder.cs" />
<Compile Include="Indexing\ReducingExecuter.cs" />
<Compile Include="Indexing\TaskSchedulerWithCustomPriority.cs" />
<Compile Include="Indexing\TasksExecuter.cs" />

0 comments on commit 11c1123

Please sign in to comment.