001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.transport;
018
019import java.io.IOException;
020
021import org.apache.activemq.command.WireFormatInfo;
022import org.apache.activemq.wireformat.WireFormat;
023import org.slf4j.Logger;
024import org.slf4j.LoggerFactory;
025
026/**
027 * Used to make sure that commands are arriving periodically from the peer of
028 * the transport.
029 */
030public class InactivityMonitor extends AbstractInactivityMonitor {
031
032    private static final Logger LOG = LoggerFactory.getLogger(InactivityMonitor.class);
033
034    private WireFormatInfo localWireFormatInfo;
035    private WireFormatInfo remoteWireFormatInfo;
036
037    private boolean ignoreRemoteWireFormat = false;
038    private boolean ignoreAllWireFormatInfo = false;
039
040    public InactivityMonitor(Transport next, WireFormat wireFormat) {
041        super(next, wireFormat);
042        if (this.wireFormat == null) {
043            this.ignoreAllWireFormatInfo = true;
044        }
045    }
046
047    @Override
048    public void start() throws Exception {
049        if (!isMonitorStarted()) {
050            startConnectCheckTask();
051        }
052        super.start();
053    }
054
055    @Override
056    protected void processInboundWireFormatInfo(WireFormatInfo info) throws IOException {
057        stopConnectCheckTask();
058        IOException error = null;
059        remoteWireFormatInfo = info;
060        try {
061            startMonitorThreads();
062        } catch (IOException e) {
063            error = e;
064        }
065        if (error != null) {
066            onException(error);
067        }
068    }
069
070    @Override
071    protected void processOutboundWireFormatInfo(WireFormatInfo info) throws IOException{
072        localWireFormatInfo = info;
073        startMonitorThreads();
074    }
075
076    @Override
077    protected synchronized void startMonitorThreads() throws IOException {
078        if (isMonitorStarted()) {
079            return;
080        }
081
082        long readCheckTime = getReadCheckTime();
083
084        if (readCheckTime > 0) {
085            setWriteCheckTime(writeCheckValueFromReadCheck(readCheckTime));
086        }
087
088        super.startMonitorThreads();
089    }
090
091    private long writeCheckValueFromReadCheck(long readCheckTime) {
092        return readCheckTime>3 ? readCheckTime/3 : readCheckTime;
093    }
094
095    @Override
096    protected boolean configuredOk() throws IOException {
097        boolean configured = false;
098        if (ignoreAllWireFormatInfo) {
099            configured = true;
100        } else if (localWireFormatInfo != null && remoteWireFormatInfo != null) {
101            if (!ignoreRemoteWireFormat) {
102                if (LOG.isDebugEnabled()) {
103                    LOG.debug("Using min of local: " + localWireFormatInfo + " and remote: " + remoteWireFormatInfo);
104                }
105
106                long readCheckTime = Math.min(localWireFormatInfo.getMaxInactivityDuration(), remoteWireFormatInfo.getMaxInactivityDuration());
107                long writeCheckTime = writeCheckValueFromReadCheck(readCheckTime);
108
109                setReadCheckTime(readCheckTime);
110                setInitialDelayTime(Math.min(localWireFormatInfo.getMaxInactivityDurationInitalDelay(), remoteWireFormatInfo.getMaxInactivityDurationInitalDelay()));
111                setWriteCheckTime(writeCheckTime);
112
113            } else {
114                if (LOG.isDebugEnabled()) {
115                    LOG.debug("Using local: " + localWireFormatInfo);
116                }
117
118                long readCheckTime = localWireFormatInfo.getMaxInactivityDuration();
119                long writeCheckTime = writeCheckValueFromReadCheck(readCheckTime);
120
121                setReadCheckTime(readCheckTime);
122                setInitialDelayTime(localWireFormatInfo.getMaxInactivityDurationInitalDelay());
123                setWriteCheckTime(writeCheckTime);
124            }
125            configured = true;
126        }
127
128        return configured;
129    }
130
131    public boolean isIgnoreAllWireFormatInfo() {
132        return ignoreAllWireFormatInfo;
133    }
134
135    public void setIgnoreAllWireFormatInfo(boolean ignoreAllWireFormatInfo) {
136        this.ignoreAllWireFormatInfo = ignoreAllWireFormatInfo;
137    }
138
139    public boolean isIgnoreRemoteWireFormat() {
140        return ignoreRemoteWireFormat;
141    }
142
143    public void setIgnoreRemoteWireFormat(boolean ignoreRemoteWireFormat) {
144        this.ignoreRemoteWireFormat = ignoreRemoteWireFormat;
145    }
146}