/* * 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.backend.jgroups.impl; import java.util.List; import java.util.Properties; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.hibernate.search.backend.IndexingMonitor; import org.hibernate.search.backend.LuceneWork; import org.hibernate.search.backend.spi.Backend; import org.hibernate.search.backend.spi.BackendQueueProcessor; import org.hibernate.search.indexes.spi.IndexManager; import org.hibernate.search.spi.WorkerBuildContext; import org.hibernate.search.util.logging.impl.Log; import org.hibernate.search.util.logging.impl.LoggerFactory; /** * JGroupsReceivingMockBackend; a JGroups based BackendQueueProcessor useful to verify * receiver state from tests. * * @author Sanne Grinovero (C) 2013 Red Hat Inc. * @since 4.3 */ public class JGroupsReceivingMockBackend implements Backend { private static final Log log = LoggerFactory.make(); private final JGroupsBackend delegate = new JGroupsMasterBackend(); @Override public void initialize(Properties properties, WorkerBuildContext context) { delegate.initialize( properties, context ); } @Override public void close() { delegate.close(); } @Override public BackendQueueProcessor createQueueProcessor(IndexManager indexManager, WorkerBuildContext context) { return new JGroupsReceivingMockBackendQueueProcessor( delegate.createQueueProcessor( indexManager, context ) ); } public static class JGroupsReceivingMockBackendQueueProcessor implements BackendQueueProcessor { private final JGroupsBackendQueueProcessor delegate; private volatile CountDownLatch threadTrap; private volatile boolean failOnMessage = false; private volatile boolean receivedAnything = false; public JGroupsReceivingMockBackendQueueProcessor(JGroupsBackendQueueProcessor delegate) { super(); this.delegate = delegate; } @Override public void close() { delegate.close(); } @Override public void applyWork(List<LuceneWork> workList, IndexingMonitor monitor) { receivedSomething(); countDownAndJoin(); } private void receivedSomething() { receivedAnything = true; } @Override public void applyStreamWork(LuceneWork singleOperation, IndexingMonitor monitor) { //Unused receivedSomething(); countDownAndJoin(); } public JGroupsBackendQueueProcessor getDelegate() { return delegate; } public void resetThreadTrap() { threadTrap = new CountDownLatch( 2 ); } public boolean wasSomethingReceived() { return receivedAnything; } public void countDownAndJoin() { if ( failOnMessage ) { throw new NullPointerException( "Simulated Failure" ); } log.trace( "[PREJOIN] Timestamp: " + System.nanoTime() ); try { threadTrap.countDown(); //Basically we want to wait forever until we are awoken; we //cap the definition of "forever" to 2 minutes to abort the test //but this should not be necessary. //The main test thread will release us ASAP so a large timeout should not //affect the actual test duration. threadTrap.await( 2, TimeUnit.MINUTES ); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } log.trace( "[POSTJOIN] Timestamp: " + System.nanoTime() ); } public int releaseBlockedThreads() { int count = (int) threadTrap.getCount(); for ( int i = 0; i < count; i++ ) { threadTrap.countDown(); } return count; } public void induceFailure() { failOnMessage = true; } } }