internal Lucene.Net.Store.Directory MakeRAMDirectoryPhysical(RAMDirectory ramDir, string indexName) { var newDir = FSDirectory.Open(new DirectoryInfo(Path.Combine(path, MonoHttpUtility.UrlEncode(IndexDefinitionStorage.FixupIndexName(indexName, path))))); Lucene.Net.Store.Directory.Copy(ramDir, newDir, true); return(newDir); }
public void DeleteIndex(string name) { Index value; if (indexes.TryGetValue(name, out value) == false) { log.InfoFormat("Ignoring delete for non existing index {0}", name); return; } log.InfoFormat("Deleting index {0}", name); value.Dispose(); Index ignored; var dirOnDisk = Path.Combine(path, MonoHttpUtility.UrlEncode(name)); if (!indexes.TryRemove(name, out ignored) || !Directory.Exists(dirOnDisk)) { return; } for (int i = 0; i < 15; i++) { try { Directory.Delete(dirOnDisk, true); break; } catch (IOException) { Thread.Sleep(100); } } }
public DynamicViewCompiler(string name, IndexDefinition indexDefinition, AbstractDynamicCompilationExtension[] extensions) { this.indexDefinition = indexDefinition; this.extensions = extensions; this.name = MonoHttpUtility.UrlEncode(name); RequiresSelectNewAnonymousType = true; }
private void InvokeSuggestionIndexing(string name, IndexDefinition definition, Index index) { foreach (var suggestion in definition.Suggestions) { var field = suggestion.Key; var suggestionOption = suggestion.Value; if (suggestionOption.Distance == StringDistanceTypes.None) { continue; } var indexExtensionKey = MonoHttpUtility.UrlEncode(field + "-" + suggestionOption.Distance + "-" + suggestionOption.Accuracy); var suggestionQueryIndexExtension = new SuggestionQueryIndexExtension( index, WorkContext, Path.Combine(Database.Configuration.IndexStoragePath, "Raven-Suggestions", name, indexExtensionKey), SuggestionQueryRunner.GetStringDistance(suggestionOption.Distance), Database.Configuration.RunInMemory, field, suggestionOption.Accuracy); Database.IndexStorage.SetIndexExtension(name, indexExtensionKey, suggestionQueryIndexExtension); } }
protected Lucene.Net.Store.Directory OpenOrCreateLuceneDirectory(IndexDefinition indexDefinition, string indexName = null) { Lucene.Net.Store.Directory directory; if (indexDefinition.IsTemp || configuration.RunInMemory) { directory = new RAMDirectory(); new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Close(); // creating index structure } else { var indexDirectory = indexName ?? IndexDefinitionStorage.FixupIndexName(indexDefinition.Name, path); var indexFullPath = Path.Combine(path, MonoHttpUtility.UrlEncode(indexDirectory)); directory = FSDirectory.Open(new DirectoryInfo(indexFullPath)); if (!IndexReader.IndexExists(directory)) { //creating index structure if we need to new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Close(); } else { // forcefully unlock locked indexes if any if (IndexWriter.IsLocked(directory)) { IndexWriter.Unlock(directory); } } } return(directory); }
public SuggestionQueryResult ExecuteSuggestionQuery(string indexName, SuggestionQuery suggestionQuery) { if (suggestionQuery == null) { throw new ArgumentNullException("suggestionQuery"); } if (string.IsNullOrWhiteSpace(suggestionQuery.Term)) { throw new ArgumentNullException("suggestionQuery.Term"); } if (string.IsNullOrWhiteSpace(indexName)) { throw new ArgumentNullException("indexName"); } if (string.IsNullOrWhiteSpace(suggestionQuery.Field)) { throw new ArgumentNullException("suggestionQuery.Field"); } if (suggestionQuery.MaxSuggestions <= 0) { suggestionQuery.MaxSuggestions = 10; } if (suggestionQuery.Accuracy <= 0 || suggestionQuery.Accuracy > 1) { suggestionQuery.Accuracy = 0.5f; } suggestionQuery.MaxSuggestions = Math.Min(suggestionQuery.MaxSuggestions, _database.Configuration.MaxPageSize); var indexExtensionKey = MonoHttpUtility.UrlEncode(suggestionQuery.Field + "-" + suggestionQuery.Distance + "-" + suggestionQuery.Accuracy); var indexExtension = _database.IndexStorage.GetIndexExtension(indexName, indexExtensionKey) as SuggestionQueryIndexExtension; IndexSearcher currentSearcher; using (_database.IndexStorage.GetCurrentIndexSearcher(indexName, out currentSearcher)) { var indexReader = currentSearcher.IndexReader; if (indexExtension != null) { return(indexExtension.Query(suggestionQuery, indexReader)); } var suggestionQueryIndexExtension = new SuggestionQueryIndexExtension( Path.Combine(_database.Configuration.IndexStoragePath, "Raven-Suggestions", indexName, indexExtensionKey), indexReader, GetStringDistance(suggestionQuery.Distance), suggestionQuery.Field, suggestionQuery.Accuracy); suggestionQueryIndexExtension.Init(indexReader); _database.IndexStorage.SetIndexExtension(indexName, indexExtensionKey, suggestionQueryIndexExtension); return(suggestionQueryIndexExtension.Query(suggestionQuery, indexReader)); } }
protected Lucene.Net.Store.Directory OpenOrCreateLuceneDirectory(string indexDirectory) { Lucene.Net.Store.Directory directory; if (configuration.RunInMemory) { directory = new RAMDirectory(); } else { directory = FSDirectory.Open(new DirectoryInfo(Path.Combine(path, MonoHttpUtility.UrlEncode(indexDirectory)))); } //creating index structure if we need to var standardAnalyzer = new StandardAnalyzer(Version.LUCENE_29); try { new IndexWriter(directory, standardAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED). Close(); } finally { standardAnalyzer.Close(); } return(directory); }
internal Lucene.Net.Store.Directory MakeRAMDirectoryPhysical(RAMDirectory ramDir, string indexName) { var newDir = new LuceneCodecDirectory(Path.Combine(path, MonoHttpUtility.UrlEncode(IndexDefinitionStorage.FixupIndexName(indexName, path))), documentDatabase.IndexCodecs.OfType <AbstractIndexCodec>()); Lucene.Net.Store.Directory.Copy(ramDir, newDir, true); return(newDir); }
private static bool TryGetDiskCacheResult(string source, string name, InMemoryRavenConfiguration configuration, out string indexFilePath, out Type type) { // It's not in the in-memory cache. See if it's been cached on disk. // // Q. Why do we cache on disk? // A. It decreases the duration of individual test runs. Instead of // recompiling the index each test run, we can just load them from disk. // It also decreases creation time for indexes that were // previously created and deleted, affecting both production and test environments. // // For more info, see http://ayende.com/blog/161218/robs-sprint-idly-indexing?key=f37cf4dc-0e5c-43be-9b27-632f61ba044f#comments-form-location var indexCacheDir = GetIndexCacheDir(configuration); string sourceHashed; using (var md5 = MD5.Create()) { var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(source)); sourceHashed = MonoHttpUtility.UrlEncode(Convert.ToBase64String(hash)); } indexFilePath = Path.Combine(indexCacheDir, IndexingUtil.StableInvariantIgnoreCaseStringHash(source) + "." + sourceHashed + "." + (Debugger.IsAttached ? "debug" : "nodebug") + ".dll"); try { if (Directory.Exists(indexCacheDir) == false) { Directory.CreateDirectory(indexCacheDir); } type = TryGetIndexFromDisk(indexFilePath, name); } catch (UnauthorizedAccessException) { // permission issues type = null; return(false); } catch (IOException) { // permission issues, probably type = null; return(false); } if (type != null) { cacheEntries.TryAdd(source, new CacheEntry { Source = source, Type = type, Usages = 1 }); { return(true); } } return(false); }
public IndexCommitPointDirectory(string indexStoragePath, string indexName, string name) { IndexFullPath = Path.Combine(indexStoragePath, MonoHttpUtility.UrlEncode(indexName)); AllCommitPointsFullPath = GetAllCommitPointsFullPath(IndexFullPath); Name = name; FullPath = Path.Combine(AllCommitPointsFullPath, Name); FileFullPath = Path.Combine(FullPath, File); DeletedKeysFile = Path.Combine(FullPath, KeysToDeleteFile); }
public void ShouldCreateCommitPointsForMapIndexes() { var index = new MapRecoveryTestIndex(); using (var server = GetNewServer(runInMemory: false)) { CommitPointAfterEachCommit(server.Database.Configuration); using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize()) { index.Execute(store); using (var session = store.OpenSession()) { session.Store(new Recovery { Name = "One", Number = 1 }); session.SaveChanges(); WaitForIndexing(store); session.Store(new Recovery { Name = "Two", Number = 2 }); session.SaveChanges(); WaitForIndexing(store); } } var commitPointsDirectory = Path.Combine(server.Database.Configuration.IndexStoragePath, MonoHttpUtility.UrlEncode(index.IndexName) + "\\CommitPoints"); Assert.True(Directory.Exists(commitPointsDirectory)); var commitPoints = Directory.GetDirectories(commitPointsDirectory); Assert.Equal(2, commitPoints.Length); foreach (var commitPoint in commitPoints) { var files = Directory.GetFiles(commitPoint); Assert.Equal(2, files.Length); Assert.Equal("index.commitPoint", Path.GetFileName(files[0])); Assert.True(Path.GetFileName(files[1]).StartsWith("segments_")); } } }
private static string GetIndexFilePath(string source, string indexCacheDir) { var hash = Encryptor.Current.Hash.Compute16(Encoding.UTF8.GetBytes(source)); var sourceHashed = MonoHttpUtility.UrlEncode(Convert.ToBase64String(hash)); var indexFilePath = Path.Combine(indexCacheDir, IndexingUtil.StableInvariantIgnoreCaseStringHash(source) + "." + sourceHashed + "." + (Debugger.IsAttached ? "debug" : "nodebug") + ".dll"); return(indexFilePath); }
private void OpenIndexOnStartup(DocumentDatabase documentDatabase, string indexName) { if (indexName == null) { throw new ArgumentNullException("indexName"); } startupLog.Debug("Loading saved index {0}", indexName); var indexDefinition = indexDefinitionStorage.GetIndexDefinition(indexName); if (indexDefinition == null) { return; } Index indexImplementation; bool resetTried = false; while (true) { try { var luceneDirectory = OpenOrCreateLuceneDirectory(indexDefinition, createIfMissing: resetTried); indexImplementation = CreateIndexImplementation(indexName, indexDefinition, luceneDirectory); break; } catch (Exception e) { if (resetTried) { throw new InvalidOperationException("Could not open / create index" + indexName + ", reset already tried", e); } resetTried = true; startupLog.WarnException("Could not open index " + indexName + ", forcibly resetting index", e); try { documentDatabase.TransactionalStorage.Batch(accessor => { accessor.Indexing.DeleteIndex(indexName); accessor.Indexing.AddIndex(indexName, indexDefinition.IsMapReduce); }); var indexDirectory = indexName; var indexFullPath = Path.Combine(path, MonoHttpUtility.UrlEncode(indexDirectory)); IOExtensions.DeleteDirectory(indexFullPath); } catch (Exception exception) { throw new InvalidOperationException("Could not reset index " + indexName, exception); } } } indexes.TryAdd(indexName, indexImplementation); }
public void ShouldHandleLegacySuggestions() { var dataDir = NewDataPath(); using (var documentStore = NewDocumentStore(runInMemory: false, dataDir: dataDir)) { documentStore.ExecuteIndex(new DefaultSuggestionIndex()); using (var s = documentStore.OpenSession()) { s.Store(new User { Name = "Ayende" }); s.Store(new User { Name = "Oren" }); s.SaveChanges(); s.Query <User, DefaultSuggestionIndex>().Customize(x => x.WaitForNonStaleResults()).ToList(); } var suggestionQueryResult = documentStore.DatabaseCommands.Suggest("DefaultSuggestionIndex", new SuggestionQuery { Field = "Name", Term = "Owen", MaxSuggestions = 10, }); Assert.Equal(1, suggestionQueryResult.Suggestions.Length); Assert.Equal("oren", suggestionQueryResult.Suggestions[0]); } // simulate legacy suggestions by renaming folder var suggestionsDir = Path.Combine(dataDir, "System\\Indexes\\Raven-Suggestions\\DefaultSuggestionIndex"); var newDirName = MonoHttpUtility.UrlEncode("Name-" + StringDistanceTypes.NGram + "-" + 0.4f); Directory.Move(Path.Combine(suggestionsDir, "Name"), Path.Combine(suggestionsDir, newDirName)); using (var documentStore = NewDocumentStore(runInMemory: false, dataDir: dataDir)) { var suggestionQueryResult = documentStore.DatabaseCommands.Suggest("DefaultSuggestionIndex", new SuggestionQuery { Field = "Name", Term = "Owen", MaxSuggestions = 10, }); Assert.Equal(1, suggestionQueryResult.Suggestions.Length); Assert.Equal("oren", suggestionQueryResult.Suggestions[0]); } Assert.True(Directory.Exists(Path.Combine(suggestionsDir, "Name"))); Assert.False(Directory.Exists(Path.Combine(suggestionsDir, newDirName))); }
protected Lucene.Net.Store.Directory OpenOrCreateLuceneDirectory( IndexDefinition indexDefinition, string indexName = null, bool createIfMissing = true) { Lucene.Net.Store.Directory directory; if (indexDefinition.IsTemp || configuration.RunInMemory) { directory = new RAMDirectory(); new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Dispose(); // creating index structure } else { var indexDirectory = indexName ?? IndexDefinitionStorage.FixupIndexName(indexDefinition.Name, path); var indexFullPath = Path.Combine(path, MonoHttpUtility.UrlEncode(indexDirectory)); directory = new LuceneCodecDirectory(indexFullPath, documentDatabase.IndexCodecs.OfType <AbstractIndexCodec>()); if (!IndexReader.IndexExists(directory)) { if (createIfMissing == false) { throw new InvalidOperationException("Index does not exists: " + indexDirectory); } WriteIndexVersion(directory); //creating index structure if we need to new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Dispose(); } else { EnsureIndexVersionMatches(indexName, directory); if (directory.FileExists("write.lock")) // force lock release, because it was still open when we shut down { IndexWriter.Unlock(directory); // for some reason, just calling unlock doesn't remove this file directory.DeleteFile("write.lock"); } if (directory.FileExists("writing-to-index.lock")) // we had an unclean shutdown { if (configuration.ResetIndexOnUncleanShutdown) { throw new InvalidOperationException("Rude shutdown detected on: " + indexDirectory); } CheckIndexAndRecover(directory, indexDirectory); directory.DeleteFile("writing-to-index.lock"); } } } return(directory); }
private void WriteIndexDefinition(IndexDefinition indexDefinition) { if (configuration.RunInMemory) { return; } var encodeIndexNameIfNeeded = FixupIndexName(indexDefinition.Name, path); var indexName = Path.Combine(path, MonoHttpUtility.UrlEncode(encodeIndexNameIfNeeded) + ".index"); // Hash the name if it's too long (as a path) File.WriteAllText(indexName, JsonConvert.SerializeObject(indexDefinition, Formatting.Indented, Default.Converters)); }
private void WriteTransformerDefinition(TransformerDefinition transformerDefinition) { if (configuration.RunInMemory) { return; } var fixedName = FixupIndexName(transformerDefinition.Name); var indexName = Path.Combine(path, MonoHttpUtility.UrlEncode(fixedName) + ".transform"); // Hash the name if it's too long (as a path) File.WriteAllText(indexName, JsonConvert.SerializeObject(transformerDefinition, Formatting.Indented, Default.Converters)); }
public DynamicViewCompiler(string name, IndexDefinition indexDefinition, AbstractDynamicCompilationExtension[] extensions, string basePath) { this.indexDefinition = indexDefinition; this.extensions = extensions; this.basePath = Path.Combine(basePath, "TemporaryIndexDefinitionsAsSource"); if (Directory.Exists(this.basePath) == false) { Directory.CreateDirectory(this.basePath); } this.name = MonoHttpUtility.UrlEncode(name); RequiresSelectNewAnonymousType = true; }
public string AddIndex(IndexDefinition indexDefinition) { var transformer = AddAndCompileIndex(indexDefinition); if (configuration.RunInMemory == false) { var encodeIndexNameIfNeeded = FixupIndexName(indexDefinition.Name, path); var indexName = Path.Combine(path, MonoHttpUtility.UrlEncode(encodeIndexNameIfNeeded) + ".index"); // Hash the name if it's too long (as a path) File.WriteAllText(indexName, JsonConvert.SerializeObject(indexDefinition, Formatting.Indented, Default.Converters)); } return(transformer.Name); }
public DynamicCompilerBase(InMemoryRavenConfiguration configuration, OrderedPartCollection <AbstractDynamicCompilationExtension> extensions, string name, string basePath) { this.configuration = configuration; this.name = name; this.extensions = extensions; if (configuration.RunInMemory == false) { this.basePath = Path.Combine(basePath, "temp"); if (Directory.Exists(this.basePath) == false) { Directory.CreateDirectory(this.basePath); } } this.name = MonoHttpUtility.UrlEncode(name); }
public DynamicViewCompiler(string name, IndexDefinition indexDefinition, OrderedPartCollection <AbstractDynamicCompilationExtension> extensions, string basePath, InMemoryRavenConfiguration configuration) { this.indexDefinition = indexDefinition; this.extensions = extensions; if (configuration.RunInMemory == false) { this.basePath = Path.Combine(basePath, "TemporaryIndexDefinitionsAsSource"); if (Directory.Exists(this.basePath) == false) { Directory.CreateDirectory(this.basePath); } } this.name = MonoHttpUtility.UrlEncode(name); RequiresSelectNewAnonymousType = true; }
protected Lucene.Net.Store.Directory OpenOrCreateLuceneDirectory( IndexDefinition indexDefinition, string indexName = null, bool createIfMissing = true) { Lucene.Net.Store.Directory directory; if (indexDefinition.IsTemp || configuration.RunInMemory) { directory = new RAMDirectory(); new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Close(); // creating index structure } else { var indexDirectory = indexName ?? IndexDefinitionStorage.FixupIndexName(indexDefinition.Name, path); var indexFullPath = Path.Combine(path, MonoHttpUtility.UrlEncode(indexDirectory)); directory = FSDirectory.Open(new DirectoryInfo(indexFullPath)); if (!IndexReader.IndexExists(directory)) { if (createIfMissing == false) { throw new InvalidOperationException("Index does not exists: " + indexDirectory); } //creating index structure if we need to new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Close(); } else { if (directory.FileExists("write.lock")) // we had an unclean shutdown { if (configuration.ResetIndexOnUncleanShutdown) { throw new InvalidOperationException("Rude shutdown detected on: " + indexDirectory); } CheckIndexAndRecover(directory, indexDirectory); IndexWriter.Unlock(directory); directory.DeleteFile("write.lock"); } } } return(directory); }
protected Lucene.Net.Store.Directory OpenOrCreateLuceneDirectory(IndexDefinition indexDefinition, string indexName = null) { Lucene.Net.Store.Directory directory; if (indexDefinition.IsTemp || configuration.RunInMemory) { directory = new RAMDirectory(); } else { var indexDirectory = indexName ?? IndexDefinitionStorage.FixupIndexName(indexDefinition.Name, path); directory = FSDirectory.Open(new DirectoryInfo(Path.Combine(path, MonoHttpUtility.UrlEncode(indexDirectory)))); } //creating index structure if we need to new IndexWriter(directory, dummyAnalyzer, IndexWriter.MaxFieldLength.UNLIMITED).Close(); return(directory); }
private void InvokeSuggestionIndexing(string name, IndexDefinition definition, Index index) { foreach (var suggestion in definition.SuggestionsOptions) { var field = suggestion; var indexExtensionKey = MonoHttpUtility.UrlEncode(field); var suggestionQueryIndexExtension = new SuggestionQueryIndexExtension( index, WorkContext, Path.Combine(Database.Configuration.IndexStoragePath, "Raven-Suggestions", name, indexExtensionKey), Database.Configuration.RunInMemory, field); Database.IndexStorage.SetIndexExtension(name, indexExtensionKey, suggestionQueryIndexExtension); } }
public static string FixupIndexName(string index, string path) { string prefix = null; if (index.StartsWith("Temp/") || index.StartsWith("Auto/")) { prefix = index.Substring(0, 5); } var fixupIndexName = MonoHttpUtility.UrlEncode(index); if (path.Length + fixupIndexName.Length > 230 || Encoding.Unicode.GetByteCount(fixupIndexName) >= 255) { using (var md5 = MD5.Create()) { var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(index)); return(prefix + Convert.ToBase64String(bytes)); } } return(index); }
public void DeleteIndex(string name) { Index value; if (indexes.TryGetValue(name, out value) == false) { log.Info("Ignoring delete for non existing index {0}", name); return; } log.Info("Deleting index {0}", name); value.Dispose(); Index ignored; var dirOnDisk = Path.Combine(path, MonoHttpUtility.UrlEncode(name)); if (!indexes.TryRemove(name, out ignored) || !Directory.Exists(dirOnDisk)) { return; } IOExtensions.DeleteDirectory(dirOnDisk); }
public void ShouldKeepLimitedNumberOfCommitPoints() { var index = new MapRecoveryTestIndex(); using (var server = GetNewServer(runInMemory: false)) { CommitPointAfterEachCommit(server.Database.Configuration); var maxNumberOfStoredCommitPoints = server.Database.Configuration.MaxNumberOfStoredCommitPoints; using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize()) { index.Execute(store); for (int i = 0; i < 2 * maxNumberOfStoredCommitPoints; i++) { using (var session = store.OpenSession()) { session.Store(new Recovery { Name = i.ToString(), Number = i }); session.SaveChanges(); WaitForIndexing(store); } var commitPointsDirectory = Path.Combine(server.Database.Configuration.IndexStoragePath, MonoHttpUtility.UrlEncode(index.IndexName) + "\\CommitPoints"); var commitPoints = Directory.GetDirectories(commitPointsDirectory); Assert.True(commitPoints.Length <= maxNumberOfStoredCommitPoints); } } } }
public void DeleteIndex(string name) { Index value; if (indexes.TryGetValue(name, out value) == false) { log.Debug("Ignoring delete for non existing index {0}", name); return; } log.Debug("Deleting index {0}", name); value.Dispose(); Index ignored; var dirOnDisk = Path.Combine(path, MonoHttpUtility.UrlEncode(name)); documentDatabase.TransactionalStorage.Batch(accessor => accessor.Lists.Remove("Raven/Indexes/QueryTime", name)); if (!indexes.TryRemove(name, out ignored) || !Directory.Exists(dirOnDisk)) { return; } IOExtensions.DeleteDirectory(dirOnDisk); }
private string GetIndexPath(string name) { var encodeIndexNameIfNeeded = FixupIndexName(name, path); return(Path.Combine(path, MonoHttpUtility.UrlEncode(encodeIndexNameIfNeeded) + ".index")); }
public SuggestionQueryResult ExecuteSuggestionQuery(string indexName, SuggestionQuery suggestionQuery) { if (suggestionQuery == null) { throw new ArgumentNullException("suggestionQuery"); } if (string.IsNullOrWhiteSpace(suggestionQuery.Term)) { throw new ArgumentNullException("suggestionQuery.Term"); } if (string.IsNullOrWhiteSpace(indexName)) { throw new ArgumentNullException("indexName"); } if (string.IsNullOrWhiteSpace(suggestionQuery.Field)) { throw new ArgumentNullException("suggestionQuery.Field"); } suggestionQuery.MaxSuggestions = Math.Min(suggestionQuery.MaxSuggestions, database.Configuration.MaxPageSize); if (suggestionQuery.MaxSuggestions <= 0) { suggestionQuery.MaxSuggestions = SuggestionQuery.DefaultMaxSuggestions; } if (suggestionQuery.Accuracy.HasValue && (suggestionQuery.Accuracy.Value <= 0f || suggestionQuery.Accuracy.Value > 1f)) { suggestionQuery.Accuracy = SuggestionQuery.DefaultAccuracy; } if (suggestionQuery.Accuracy.HasValue == false) { suggestionQuery.Accuracy = SuggestionQuery.DefaultAccuracy; } if (suggestionQuery.Distance.HasValue == false) { suggestionQuery.Distance = StringDistanceTypes.Default; } var definition = database.IndexDefinitionStorage.GetIndexDefinition(indexName); var indexExtensionKey = MonoHttpUtility.UrlEncode(suggestionQuery.Field + "-" + suggestionQuery.Distance + "-" + suggestionQuery.Accuracy); var indexExtension = database.IndexStorage.GetIndexExtensionByPrefix(indexName, indexExtensionKey) as SuggestionQueryIndexExtension; IndexSearcher currentSearcher; using (database.IndexStorage.GetCurrentIndexSearcher(definition.IndexId, out currentSearcher)) { if (currentSearcher == null) { throw new InvalidOperationException("Could not find current searcher"); } var indexReader = currentSearcher.IndexReader; if (indexExtension != null) { return(indexExtension.Query(suggestionQuery, indexReader)); } var suggestionQueryIndexExtension = new SuggestionQueryIndexExtension( database.WorkContext, Path.Combine(database.Configuration.IndexStoragePath, "Raven-Suggestions", indexName, indexExtensionKey), GetStringDistance(suggestionQuery.Distance ?? StringDistanceTypes.Default), indexReader.Directory() is RAMDirectory, suggestionQuery.Field, suggestionQuery.Accuracy ?? 0.5f); database.IndexStorage.SetIndexExtension(indexName, indexExtensionKey, suggestionQueryIndexExtension); long _; var task = Task.Factory.StartNew(() => suggestionQueryIndexExtension.Init(indexReader)); database.Tasks.AddTask(task, new object(), new TaskActions.PendingTaskDescription { Payload = indexName, TaskType = TaskActions.PendingTaskType.SuggestionQuery, StartTime = SystemTime.UtcNow }, out _); // wait for a bit for the suggestions to complete, but not too much (avoid IIS resets) task.Wait(15000, database.WorkContext.CancellationToken); return(suggestionQueryIndexExtension.Query(suggestionQuery, indexReader)); } }