在ASP.NET MVC站点中使用Lucene.Net进行目录锁定错误

我正在构建一个ASP.NET MVC站点,我想使用Lucene.Net进行搜索。 我已经构建了一个SearchController及其所有方法,但是我在运行时遇到一个错误,这个错误是在首次初始化SearchController时发生的。

在SearchController中,这是我如何创建IndexWriter:

public static string IndexLocation = HostingEnvironment.MapPath("~/lucene"); public static Lucene.Net.Analysis.Standard.StandardAnalyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(); public static IndexWriter writer = new IndexWriter(IndexLocation,analyzer); 

错误发生在最后一行。 这是我得到的信息:

Lucene.Net.Store.LockObtainFailedException: Lock获取超时 :SimpleFSLock @ C:\ Users \ Username \ Desktop \ SiteSolution \ Site \ lucene \ write.lock

此外,这是堆栈跟踪:

 [LockObtainFailedException: Lock obtain timed out: SimpleFSLock@C:\Users\Username\Desktop\SiteSolution\Site\lucene\write.lock] Lucene.Net.Store.Lock.Obtain(Int64 lockWaitTimeout) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Store\Lock.cs:107 Lucene.Net.Index.IndexWriter.Init(Directory d, Analyzer a, Boolean create, Boolean closeDir, IndexDeletionPolicy deletionPolicy, Boolean autoCommit, Int32 maxFieldLength, IndexingChain indexingChain, IndexCommit commit) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Index\IndexWriter.cs:1827 Lucene.Net.Index.IndexWriter.Init(Directory d, Analyzer a, Boolean closeDir, IndexDeletionPolicy deletionPolicy, Boolean autoCommit, Int32 maxFieldLength, IndexingChain indexingChain, IndexCommit commit) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Index\IndexWriter.cs:1801 Lucene.Net.Index.IndexWriter..ctor(String path, Analyzer a) in C:\Users\Username\Desktop\Lucene.Net_2_9_2\src\Lucene.Net\Index\IndexWriter.cs:1350 Site.Controllers.SearchController..cctor() in C:\Users\Username\Desktop\SiteSolution\Site\Controllers\SearchController.cs:95 [TypeInitializationException: The type initializer for 'Site.Controllers.SearchController' threw an exception.] [TargetInvocationException: Exception has been thrown by the target of an invocation.] System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +86 System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +230 System.Activator.CreateInstance(Type type, Boolean nonPublic) +67 System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80 [InvalidOperationException: An error occurred when trying to create a controller of type 'Site.Controllers.SearchController'. Make sure that the controller has a parameterless public constructor.] System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +190 System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +68 System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +118 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +46 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +63 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +13 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8682818 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

我该如何解决这个问题?

更新:我已经开始再次研究这个特定项目了,似乎我还没有完全解决这个问题。

真正的问题是在索引使用结束后没有删除write.lock文件 。 根据我接受的答案,我理解基本的实现逻辑,但我不确定我是否已正确实现它。 以下是我class级中可能无效的其他一些方法:

  public ActionResult Search(string query) { var reader = writer.GetReader(); // Get reader from writer var searcher = new IndexSearcher(reader); // Build IndexSearch //Execute search... // Dispose of objects searcher = null; reader = null; return View(); } public void AddToIndex(Document doc) { writer.AddDocument(doc); writer.Flush(); writer.Optimize(); writer.Flush(); } private bool disposed = false; protected override void Dispose(bool disposing) { if (!disposed) { if (disposing) { // Release managed resources. } try { writer.Close(); writer = null; } catch { } // Release unmanaged resources. // Set large fields to null. // Call Dispose on your base class. disposed = true; } base.Dispose(disposing); } 

有什么想法吗?

发生这种情况的原因是编写器创建了一个名为write.lock的空文件作为跨进程锁。 当该文件存在时,Lucene假定有人在该目录上有写锁定。

如果错误地终止进程,则不会删除该文件。 所以Lucene认为有人仍然坚持锁定。 这就是为什么你应该总是有一个关闭索引的finally语句。

如果你确定该文件存在错误(即没有运行Lucene进程),只需删除该文件即可。 但是,您的索引可能处于损坏状态,因为写作明显在中途终止。

似乎是对lucene的死锁。

如果假设没有索引更新到集合中,
只需删除此锁定文件C:\Users\Username\Desktop\SiteSolution\Site\lucene\write.lock

之后重新运行索引编写。

 try { writer = new IndexWriter(directory, new StandardAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); } catch (LockObtainFailedException ex) { DirectoryInfo indexDirInfo = new DirectoryInfo(directory); FSDirectory indexFSDir = FSDirectory.Open(indexDirInfo, new Lucene.Net.Store.SimpleFSLockFactory(indexDirInfo)); IndexWriter.Unlock(indexFSDir); writer = new IndexWriter(directory, new StandardAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); } 

自己研究这个似乎是indended方法将使用多个物理索引,然后使用IndexWriter的.addIndexesNoOptimize或.addIndexes合并它们以合并所有并发索引更改。

Lucene文档

没有自己检查但是不会这样(在创建azureDirectory对象后写)?

 azureDirectory.ClearLock("write.lock") 

我遇到了同样的问题,我正在使用IProviderContext。 在我的情况下,我不得不:优化,提交和处置ProviderContext。

 providerContext.Optimize(); providerContext.Commit(); providerContext.Dispose(); 

我希望这有帮助。 实现上面的代码片段后,我的索引成功重建。