/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.test.engine.optimizations;
import static org.fest.assertions.Assertions.assertThat;
import java.io.File;
import java.io.Serializable;
import java.util.Map;
import org.apache.lucene.index.IndexReader;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.search.Search;
import org.hibernate.search.SearchFactory;
import org.hibernate.search.test.SearchTestBase;
import org.hibernate.search.testsupport.TestForIssue;
import org.hibernate.search.testsupport.junit.SkipOnElasticsearch;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* Test that the IndexReader can see an optmized index before the factory is closed.
*
* @author Davide D'Alto
*/
@TestForIssue(jiraKey = "HSEARCH-1681")
@Category(SkipOnElasticsearch.class) // IndexReaders are specific to the Lucene backend
public class IndexReaderSeeOptimizedIndexTest extends SearchTestBase {
private String indexBasePath;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
try ( Session session = openSession() ) {
Transaction tx = session.beginTransaction();
String band = "Impaled Northern Moonforest";
SongWithLongTitle song1 = new SongWithLongTitle();
song1.setId( 1L );
song1.setBand( band );
song1.setTitle( "Gazing At The Blasphemous Moon While Perched Atop A Very Very Very Very Very Very Very Forsaken Crest Of The Northern Mountain" );
SongWithLongTitle song2 = new SongWithLongTitle();
song2.setId( 2L );
song2.setBand( band );
song2.setTitle( "Summoning The Unholy Frozen Winterdemons To The Grimmest And Most Frostbitten Inverted Forest Of Abazagorath" );
SongWithLongTitle song3 = new SongWithLongTitle();
song3.setId( 3L );
song3.setBand( band );
song3.setTitle( "Awaiting The Frozen Blasphemy Of The Necroyeti's Lusting Necrobation Upon The Altar Of Voxrfszzzisnzf" );
session.persist( song1 );
session.persist( song2 );
session.persist( song3 );
tx.commit();
}
}
@After
public void deleteAll() throws Exception {
openSessionFactory();
deleteEntities( 1L, 2L, 3L );
super.tearDown();
}
private void deleteEntities(Serializable... ids) {
try ( Session session = openSession() ) {
Transaction tx = session.beginTransaction();
for ( Serializable id : ids ) {
SongWithLongTitle entity = session.get( SongWithLongTitle.class, id );
if ( entity != null ) {
session.delete( entity );
}
}
tx.commit();
}
}
public static long folderSize(File directory) {
long length = 0;
for ( File file : directory.listFiles() ) {
if ( file.isFile() ) {
length += file.length();
}
else {
length += folderSize( file );
}
}
return length;
}
@Override
public void configure(Map<String, Object> settings) {
settings.put( "hibernate.search.default.directory_provider", "filesystem" );
indexBasePath = (String) settings.get( "hibernate.search.default.indexBase" );
}
@Test
public void testFolderSize() throws Exception {
File indexFolder = new File( indexBasePath );
long initialFolderSize = folderSize( indexFolder );
try ( Session session = openSession() ) {
session.beginTransaction();
SearchFactory searchFactory = Search.getFullTextSession( session ).getSearchFactory();
searchFactory.optimize();
session.getTransaction().commit();
}
long afterSessionClosed = folderSize( indexFolder );
closeSessionFactory();
long afterFactoryClosed = folderSize( indexFolder );
assertThat( afterSessionClosed ).isEqualTo( afterFactoryClosed );
assertThat( afterFactoryClosed ).isLessThan( initialFolderSize );
}
@Test
public void testIndexReaderAccessOptimizedIndex() throws Exception {
try ( Session session = openSession() ) {
session.beginTransaction();
session.delete( session.load( SongWithLongTitle.class, 1L ) );
session.getTransaction().commit();
session.clear();
session.beginTransaction();
SearchFactory searchFactory = Search.getFullTextSession( session ).getSearchFactory();
try (IndexReader indexReader = indexReader( searchFactory )) {
assertThat( indexReader.hasDeletions() )
.as( "IndexReader should see the deletions before the optimization" )
.isTrue();
searchFactory.optimize();
session.getTransaction().commit();
}
try (IndexReader indexReader = indexReader( searchFactory )) {
assertThat( indexReader.hasDeletions() )
.as( "IndexReader should see some deletions after optimization" )
.isFalse();
}
}
finally {
closeSessionFactory();
}
}
private IndexReader indexReader(SearchFactory searchFactory) {
return searchFactory.getIndexReaderAccessor().open( SongWithLongTitle.class );
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { SongWithLongTitle.class };
}
}