All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.activemq.transport.WriteTimeoutFilter Maven / Gradle / Ivy

There is a newer version: 6.1.2
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.transport;

import java.io.IOException;
import java.net.Socket;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.transport.tcp.TimeStampStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This filter implements write timeouts for socket write operations.
 * When using blocking IO, the Java implementation doesn't have an explicit flag
 * to set a timeout, and can cause operations to block forever (or until the TCP stack implementation times out the retransmissions,
 * which is usually around 13-30 minutes).
* To enable this transport, in the transport URI, simpley add
* transport.soWriteTimeout=.
* For example (15 second timeout on write operations to the socket):
*

 * <transportConnector
 *     name="tcp1"
 *     uri="tcp://127.0.0.1:61616?transport.soTimeout=10000&transport.soWriteTimeout=15000"
 * />
 * 

* For example (enable default timeout on the socket):
*

 * <transportConnector
 *     name="tcp1"
 *     uri="tcp://127.0.0.1:61616?transport.soTimeout=10000&transport.soWriteTimeout=15000"
 * />
 * 
* @author Filip Hanik * */ public class WriteTimeoutFilter extends TransportFilter { private static final Logger LOG = LoggerFactory.getLogger(WriteTimeoutFilter.class); protected static ConcurrentLinkedQueue writers = new ConcurrentLinkedQueue(); protected static AtomicInteger messageCounter = new AtomicInteger(0); protected static TimeoutThread timeoutThread = new TimeoutThread(); protected static long sleep = 5000l; protected long writeTimeout = -1; public WriteTimeoutFilter(Transport next) { super(next); } @Override public void oneway(Object command) throws IOException { try { registerWrite(this); super.oneway(command); } catch (IOException x) { throw x; } finally { deRegisterWrite(this,false,null); } } public long getWriteTimeout() { return writeTimeout; } public void setWriteTimeout(long writeTimeout) { this.writeTimeout = writeTimeout; } public static long getSleep() { return sleep; } public static void setSleep(long sleep) { WriteTimeoutFilter.sleep = sleep; } protected TimeStampStream getWriter() { return next.narrow(TimeStampStream.class); } protected Socket getSocket() { return next.narrow(Socket.class); } protected static void registerWrite(WriteTimeoutFilter filter) { writers.add(filter); } protected static boolean deRegisterWrite(WriteTimeoutFilter filter, boolean fail, IOException iox) { boolean result = writers.remove(filter); if (result) { if (fail) { String message = "Forced write timeout for:"+filter.getNext().getRemoteAddress(); LOG.warn(message); Socket sock = filter.getSocket(); if (sock==null) { LOG.error("Destination socket is null, unable to close socket.("+message+")"); } else { try { sock.close(); }catch (IOException ignore) { } } } } return result; } @Override public void start() throws Exception { super.start(); } @Override public void stop() throws Exception { super.stop(); } protected static class TimeoutThread extends Thread { static AtomicInteger instance = new AtomicInteger(0); boolean run = true; public TimeoutThread() { setName("WriteTimeoutFilter-Timeout-"+instance.incrementAndGet()); setDaemon(true); setPriority(Thread.MIN_PRIORITY); start(); } public void run() { while (run) { boolean error = false; try { if (!interrupted()) { Iterator filters = writers.iterator(); while (run && filters.hasNext()) { WriteTimeoutFilter filter = filters.next(); if (filter.getWriteTimeout()<=0) continue; //no timeout set long writeStart = filter.getWriter().getWriteTimestamp(); long delta = (filter.getWriter().isWriting() && writeStart>0)?System.currentTimeMillis() - writeStart:-1; if (delta>filter.getWriteTimeout()) { WriteTimeoutFilter.deRegisterWrite(filter, true,null); }//if timeout }//while }//if interrupted try { Thread.sleep(getSleep()); error = false; } catch (InterruptedException x) { //do nothing } }catch (Throwable t) { //make sure this thread never dies if (!error) { //use error flag to avoid filling up the logs LOG.error("WriteTimeout thread unable validate existing sockets.",t); error = true; } } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy