1

we recently upgraded to Hibernate Search 4.1 and are getting errors when we run our JUnit tests based on the changes hibernate made with regards to locks. When we run Junit tests with the AbstractTransactionalJUnit4SpringContextTests we often see locks left after each test. In reviewing (How to handle Hibernate-Search index recovery) we tried the native locks, but this did not resolve the issue.

We've tried out the various locking mechanisms (simple, single, and native) using the default directory provider (Filestore) and regularly see messages like:

build   20-Apr-2012 07:07:53    ERROR 2012-04-20 07:07:53,290 154053 (LogErrorHandler.java:83) org.hibernate.search.exception.impl.LogErrorHandler  - HSEARCH000058: HSEARCH000117: IOException on the IndexWriter
build   20-Apr-2012 07:07:53    org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@target/indexes/Resource/write.lock
build   20-Apr-2012 07:07:53        at org.apache.lucene.store.Lock.obtain(Lock.java:84)
build   20-Apr-2012 07:07:53        at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:1108)

or

build   19-Apr-2012 19:31:09    ERROR 2012-04-19 19:31:09,395 153552 (LuceneBackendTaskStreamer.java:61) org.hibernate.search.backend.impl.lucene.LuceneBackendTaskStreamer  - HSEARCH000072: Couldn't open the IndexWriter because of previous error: operation skipped, index ouf of sync!

Some of these messages seem to show the lock issue cascading from one test to another, hence the need for the reset, and some may be valid because the tests are testing 'invalid' behaviors and how our application reacts to them, but often because of cases like this where the ID is null

build   19-Apr-2012 19:31:11    Primary Failure:
build   19-Apr-2012 19:31:11        Entity org.tdar.core.bean.resource.CodingSheet  Id null  Work Type  org.hibernate.search.backend.PurgeAllLuceneWork

But, regardless, we need to make sure that one test does not effect another.

In reading some of the discussions (email discussion on directory providers) it was suggested that the RAM based directory provider might be a better option, but we'd prefer to use the same provider as we use in production wherever possible.

How should we be resetting HibernateSearch between tests to clean up lock files and reset potential issues where the index is out-of-sync or corrupted? At the beginning of the test suite, we wipe the index directory, is it recommended to wipe it after every test?

thanks

Community
  • 1
  • 1
adam
  • 1,067
  • 11
  • 24
  • Some of this problem seems related to using an exclusive vs. non-exclusive locking strategy: **hibernate.search.default.exclusive_index_use=false** which fixes the errors listed above, but clarification on best practices for testing are still desired – adam Apr 20 '12 at 15:22

2 Answers2

2

If you have stale locks in the directory, it means that Hibernate Search wasn't shut down properly as it certainly will close the locks.

If you start a new Hibernate SessionFactory in each test, you should make sure it's closed as well after the test was run:

org.hibernate.SessionFactory.close()

(This is often missing in many examples as there are no noticeable problems when forgetting to close a Hibernate SessionFactory, but has never been optional and might leak connections or threads).

The thread from the Hibernate mailing list you linked to ended up changing the locks to use native handles in Hibernate Search 4.1, so that locks are cleaned up automatically in case the JVM crashes or is killed. But in your case I guess you're not killing the VM between tests, so you just need to make sure locks are released properly by shutting down the service.

exclusive_index_use=false hides the problem as the IndexWriter will be closed at the end of each transaction. That makes it slower though, as it's significantly more efficient to reuse the IndexWriter. The reason you have this issue after upgrading to Hibernate Search 4.1 is that this option was changed to true by default. But even then, you should still close it properly.

Sanne
  • 6,027
  • 19
  • 34
0

My understanding is that Spring manages the SessionFactory lifecycle, so it is not necessary to call close() at any time.

I have seen this locking error when there are multiple contexts loaded during a test run. For example, the first context creates the locks on the index file. The second context attempt to access the same indexes and fails due to the existence of the open SessionFactory from the first context.

I have fixed this by using @DirtiesContext which closes context before the next is instantiated

HandyManDan
  • 478
  • 5
  • 11