/*
* 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.Collections;
import java.util.List;
import java.util.function.Supplier;
import org.hibernate.search.backend.IndexingMonitor;
import org.hibernate.search.backend.LuceneWork;
import org.hibernate.search.backend.spi.BackendQueueProcessor;
/**
* This index backend is able to switch dynamically between a standard
* Lucene index writing backend and one which sends work remotely over
* a JGroups channel.
*
* @author Lukasz Moren
* @author Sanne Grinovero (C) 2012 Red Hat Inc.
* @author Ales Justin
*/
public class JGroupsBackendQueueProcessor implements BackendQueueProcessor {
private final NodeSelectorStrategy selectionStrategy;
private final JGroupsBackendQueueTask jgroupsProcessor;
private final Supplier<BackendQueueProcessor> delegatedBackendFactory;
private volatile BackendQueueProcessor delegate;
public JGroupsBackendQueueProcessor(NodeSelectorStrategy selectionStrategy,
JGroupsBackendQueueTask jgroupsProcessor,
Supplier<BackendQueueProcessor> delegatedBackendFactory) {
this.selectionStrategy = selectionStrategy;
this.jgroupsProcessor = jgroupsProcessor;
this.delegatedBackendFactory = delegatedBackendFactory;
if ( selectionStrategy.isIndexOwnerLocal() ) {
/*
* Eager initialization if we know from the start we are the master.
* This allows in particular the delegate backend to fail fast
* if there is a configuration issue.
*/
getOrCreateDelegate();
}
}
@Override
public synchronized void close() {
if ( delegate != null ) {
delegate.close();
}
}
@Override
public void applyWork(List<LuceneWork> workList, IndexingMonitor monitor) {
if ( selectionStrategy.isIndexOwnerLocal() ) {
getOrCreateDelegate().applyWork( workList, monitor );
}
else {
if ( workList == null ) {
throw new IllegalArgumentException( "workList should not be null" );
}
jgroupsProcessor.sendLuceneWorkList( workList );
}
}
@Override
public void applyStreamWork(LuceneWork singleOperation, IndexingMonitor monitor) {
if ( selectionStrategy.isIndexOwnerLocal() ) {
getOrCreateDelegate().applyStreamWork( singleOperation, monitor );
}
else {
//TODO optimize for single operation?
jgroupsProcessor.sendLuceneWorkList( Collections.singletonList( singleOperation ) );
}
}
private BackendQueueProcessor getOrCreateDelegate() {
if ( delegate != null ) {
return delegate;
}
synchronized ( this ) {
if ( delegate != null ) {
return delegate;
}
delegate = delegatedBackendFactory.get();
return delegate;
}
}
public boolean blocksForACK() {
return jgroupsProcessor.blocksForACK();
}
public BackendQueueProcessor getExistingDelegate() {
return delegate;
}
public long getMessageTimeout() {
return jgroupsProcessor.getMessageTimeout();
}
}