/*
* 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.concurrency;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.backend.IndexingMonitor;
import org.hibernate.search.backend.LuceneWork;
import org.hibernate.search.backend.impl.LocalBackendQueueProcessor;
import org.hibernate.search.test.SearchTestBase;
import org.hibernate.search.testsupport.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
@TestForIssue(jiraKey = "HSEARCH-1623")
public class ConcurrentFlushTest extends SearchTestBase {
private static final int STORED_ENTRIES = 150;
private static final AtomicInteger indexedElements = new AtomicInteger();
public class InsertEntityJob implements Runnable {
private final SessionFactory sessionFactory;
private final int jobNumber;
public InsertEntityJob(SessionFactory sessionFactory, int jobNumber) {
this.sessionFactory = sessionFactory;
this.jobNumber = jobNumber;
}
@Override
public void run() {
Session session = sessionFactory.openSession();
try {
Transaction transaction = session.beginTransaction();
try {
FlushedStuff stuff = new FlushedStuff();
stuff.id = jobNumber;
stuff.name = "Some job code #" + jobNumber;
session.save( stuff );
session.flush();
}
finally {
transaction.commit();
}
}
catch (HibernateException e) {
e.printStackTrace();
}
finally {
session.close();
}
}
}
@Test
public void testPropertiesIndexing() {
ExecutorService executorService = Executors.newFixedThreadPool( 10 );
for ( int i = 0; i < STORED_ENTRIES; i++ ) {
executorService.execute( new InsertEntityJob( getSessionFactory(), i ) );
}
try {
executorService.shutdown();
executorService.awaitTermination( 10, TimeUnit.MINUTES );
}
catch (InterruptedException e) {
Assert.fail( "unexpected error " + e.getMessage() );
}
Assert.assertEquals( STORED_ENTRIES, indexedElements.get() );
}
@Indexed
@Entity
@Table(name = "FLUSHEDSTUFF")
public static class FlushedStuff {
@Id
public int id;
public String name;
}
public static class SlowCountingBackend extends LocalBackendQueueProcessor {
@Override
public void applyWork(List<LuceneWork> workList, IndexingMonitor monitor) {
// Increment counter
indexedElements.incrementAndGet();
// Then sleep
try {
Thread.sleep( 10 );
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class[]{ FlushedStuff.class };
}
@Override
public void configure(Map<String,Object> cfg) {
cfg.put( "hibernate.search.default.worker.backend", SlowCountingBackend.class.getName() );
}
}