/** * Amanuensis, a distributed Lucene Index Writer for Infinispan * * Copyright (c) 2011, Tristan Tarrant * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package net.dataforte.infinispan.amanuensis.backend.jgroups; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import net.dataforte.commons.slf4j.LoggerFactory; import net.dataforte.infinispan.amanuensis.AmanuensisManager; import net.dataforte.infinispan.amanuensis.IndexOperations; import net.dataforte.infinispan.amanuensis.IndexerException; import net.dataforte.infinispan.amanuensis.OperationDispatcher; import org.infinispan.remoting.transport.jgroups.JGroupsAddress; import org.jgroups.Address; import org.jgroups.Message; import org.jgroups.blocks.Request; import org.jgroups.blocks.RequestOptions; import org.jgroups.blocks.mux.MuxMessageDispatcher; import org.slf4j.Logger; /** * This class takes care of dispatching {@link IndexOperations} messages from * the slaves to the master. * * @author Tristan Tarrant */ public class JGroupsOperationDispatcher implements OperationDispatcher { private static final Logger log = LoggerFactory.make(); private AmanuensisManager manager; private MuxMessageDispatcher messageDispatcher; private RequestOptions requestOptions; private int maxRetries = 10; private int minTimeout = 10000; public JGroupsOperationDispatcher(AmanuensisManager manager, MuxMessageDispatcher messageDispatcher) { this.manager = manager; this.messageDispatcher = messageDispatcher; this.requestOptions = new RequestOptions(Request.GET_ALL, 10000); // We want synchronous, and we can wait for 10 seconds } public RequestOptions getRequestOptions() { return requestOptions; } public void setRequestOptions(RequestOptions requestOptions) { this.requestOptions = requestOptions; } public int getMaxRetries() { return maxRetries; } public void setMaxRetries(int retries) { this.maxRetries = retries; } public int getMinTimeout() { return minTimeout; } public void setMinTimeout(int minTimeout) { this.minTimeout = minTimeout; } @Override public void dispatch(final IndexOperations ops) throws IndexerException { final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); executor.scheduleWithFixedDelay(new Runnable() { int retryCount = 0; @Override public void run() { Address dest = ((JGroupsAddress) manager.getMasterAddress()).getJGroupsAddress(); Address src = ((JGroupsAddress) manager.getLocalAddress()).getJGroupsAddress(); if(dest.equals(src)) { try { manager.dispatchOperations(ops); executor.shutdown(); return; } catch (IndexerException e) { // Fall through } } Message message = new Message(dest, src, ops); if (log.isTraceEnabled()) { log.trace("Sending {} to {}", ops.toString(), dest.toString()); } try { messageDispatcher.sendMessage(message, requestOptions); // No exception was raised, stop the executor executor.shutdown(); } catch (Exception e) { ++retryCount; if(log.isDebugEnabled()) { log.debug("Error while sending {} to {}", ops.toString(), dest.toString()); } if(retryCount<maxRetries) { log.warn("Sending operations to {} failed, try #{}", dest.toString(), retryCount); } else { log.error("Could not send operations to "+dest.toString()+" after "+maxRetries + "tries, giving up", e); } } }}, 0, minTimeout, TimeUnit.MILLISECONDS); } }