You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2008/04/09 13:34:36 UTC
svn commit: r646276 - in
/mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive:
KeepAliveFilter.java KeepAlivePolicy.java KeepAliveRequestTimeoutHandler.java
Author: trustin
Date: Wed Apr 9 04:34:35 2008
New Revision: 646276
URL: http://svn.apache.org/viewvc?rev=646276&view=rev
Log:
Resolved issue: DIRMINA-568 - Improve KeepAliveFilter to provide customizable timeout handler.
* Added KeepAliveRequestTimeoutHandler
Added:
mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java (with props)
Removed:
mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAlivePolicy.java
Modified:
mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveFilter.java
Modified: mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveFilter.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveFilter.java?rev=646276&r1=646275&r2=646276&view=diff
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveFilter.java (original)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveFilter.java Wed Apr 9 04:34:35 2008
@@ -30,8 +30,6 @@
import org.apache.mina.common.IoSession;
import org.apache.mina.common.IoSessionConfig;
import org.apache.mina.common.WriteRequest;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* An {@link IoFilter} that sends a keep-alive request on
@@ -65,8 +63,9 @@
* <td>You want a keep-alive request is sent when the reader is idle.
* Once the request is sent, the response for the request should be
* received within <tt>keepAliveRequestTimeout</tt> seconds. Otherwise,
- * the specified {@link KeepAlivePolicy} will be enforced. If a keep-alive
- * request is received, its response also should be sent back.</td>
+ * the specified {@link KeepAliveRequestTimeoutHandler} will be invoked.
+ * If a keep-alive request is received, its response also should be sent back.
+ * </td>
* <td>Both {@link KeepAliveMessageFactory#getRequest(IoSession)} and
* {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must
* return a non-<tt>null</tt>.</td>
@@ -80,8 +79,10 @@
* </td>
* <td>Both {@link KeepAliveMessageFactory#getRequest(IoSession)} and
* {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must
- * return a non-<tt>null</tt>, and the <tt>policy</tt> property
- * should be set to {@link KeepAlivePolicy#OFF} or {@link KeepAlivePolicy#LOG}.
+ * return a non-<tt>null</tt>, and the <tt>timeoutHandler</tt> property
+ * should be set to {@link KeepAliveRequestTimeoutHandler#NOOP},
+ * {@link KeepAliveRequestTimeoutHandler#LOG} or the custom {@link KeepAliveRequestTimeoutHandler}
+ * implementation that doesn't affect the session state nor throw an exception.
* </td>
* </tr>
* <tr valign="top">
@@ -99,8 +100,8 @@
* <td>{@link KeepAliveMessageFactory#getRequest(IoSession)} must return
* a non-<tt>null</tt>,
* {@link KeepAliveMessageFactory#getResponse(IoSession, Object)} must
- * return <tt>null</tt> and the {@link KeepAlivePolicy} must be set to
- * {@link KeepAlivePolicy#OFF}.</td>
+ * return <tt>null</tt> and the <tt>timeoutHandler</tt> must be set to
+ * {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER}.</td>
* </tr>
* <tr valign="top">
* <td>Silent Listener</td>
@@ -116,12 +117,22 @@
* {@link KeepAliveMessageFactory#isResponse(IoSession, Object)} properly
* whatever case you chose.
*
- * <h2>Enforcing a policy</h2>
+ * <h2>Handling timeout</h2>
+ *
+ * {@link KeepAliveFilter} will notify its {@link KeepAliveRequestTimeoutHandler}
+ * when {@link KeepAliveFilter} didn't receive the response message for a sent
+ * keep-alive message. The default handler is {@link KeepAliveRequestTimeoutHandler#CLOSE},
+ * but you can use other presets such as {@link KeepAliveRequestTimeoutHandler#NOOP},
+ * {@link KeepAliveRequestTimeoutHandler#LOG} or {@link KeepAliveRequestTimeoutHandler#EXCEPTION}.
+ * You can even implement your own handler.
*
- * You can enforce a predefined policy by specifying a {@link KeepAlivePolicy}.
- * The default policy is {@link KeepAlivePolicy#CLOSE}. Setting the policy
- * to {@link KeepAlivePolicy#OFF} stops this filter from waiting for response
- * messages and therefore disables <tt>keepAliveRequestTimeout</tt> property.
+ * <h3>Special handler: {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER}</h3>
+ *
+ * {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER} is a special handler which is
+ * dedicated for the 'deaf speaker' mode mentioned above. Setting the
+ * <tt>timeoutHandler</tt> property to {@link KeepAliveRequestTimeoutHandler#DEAF_SPEAKER}
+ * stops this filter from waiting for response messages and therefore disables
+ * response timeout detection.
*
* @author The Apache MINA Project (dev@mina.apache.org)
* @version $Rev$, $Date$
@@ -133,32 +144,30 @@
private final KeepAliveMessageFactory messageFactory;
private final IdleStatus interestedIdleStatus;
- private volatile KeepAlivePolicy policy;
- private volatile int keepAliveRequestInterval;
- private volatile int keepAliveRequestTimeout;
+ private volatile KeepAliveRequestTimeoutHandler requestTimeoutHandler;
+ private volatile int requestInterval;
+ private volatile int requestTimeout;
private volatile boolean forwardEvent;
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
/**
* Creates a new instance with the default properties.
* The default property values are:
* <ul>
* <li><tt>interestedIdleStatus</tt> - {@link IdleStatus#READER_IDLE}</li>
- * <li><tt>policy</tt> = {@link KeepAlivePolicy#CLOSE}</li>
+ * <li><tt>policy</tt> = {@link KeepAliveRequestTimeoutHandler#CLOSE}</li>
* <li><tt>keepAliveRequestInterval</tt> - 60 (seconds)</li>
* <li><tt>keepAliveRequestTimeout</tt> - 30 (seconds)</li>
* </ul>
*/
public KeepAliveFilter(KeepAliveMessageFactory messageFactory) {
- this(messageFactory, IdleStatus.READER_IDLE, KeepAlivePolicy.CLOSE);
+ this(messageFactory, IdleStatus.READER_IDLE, KeepAliveRequestTimeoutHandler.CLOSE);
}
/**
* Creates a new instance with the default properties.
* The default property values are:
* <ul>
- * <li><tt>policy</tt> = {@link KeepAlivePolicy#CLOSE}</li>
+ * <li><tt>policy</tt> = {@link KeepAliveRequestTimeoutHandler#CLOSE}</li>
* <li><tt>keepAliveRequestInterval</tt> - 60 (seconds)</li>
* <li><tt>keepAliveRequestTimeout</tt> - 30 (seconds)</li>
* </ul>
@@ -166,7 +175,7 @@
public KeepAliveFilter(
KeepAliveMessageFactory messageFactory,
IdleStatus interestedIdleStatus) {
- this(messageFactory, interestedIdleStatus, KeepAlivePolicy.CLOSE, 60, 30);
+ this(messageFactory, interestedIdleStatus, KeepAliveRequestTimeoutHandler.CLOSE, 60, 30);
}
/**
@@ -179,7 +188,7 @@
* </ul>
*/
public KeepAliveFilter(
- KeepAliveMessageFactory messageFactory, KeepAlivePolicy policy) {
+ KeepAliveMessageFactory messageFactory, KeepAliveRequestTimeoutHandler policy) {
this(messageFactory, IdleStatus.READER_IDLE, policy, 60, 30);
}
@@ -193,7 +202,7 @@
*/
public KeepAliveFilter(
KeepAliveMessageFactory messageFactory,
- IdleStatus interestedIdleStatus, KeepAlivePolicy policy) {
+ IdleStatus interestedIdleStatus, KeepAliveRequestTimeoutHandler policy) {
this(messageFactory, interestedIdleStatus, policy, 60, 30);
}
@@ -202,7 +211,7 @@
*/
public KeepAliveFilter(
KeepAliveMessageFactory messageFactory,
- IdleStatus interestedIdleStatus, KeepAlivePolicy policy,
+ IdleStatus interestedIdleStatus, KeepAliveRequestTimeoutHandler policy,
int keepAliveRequestInterval, int keepAliveRequestTimeout) {
if (messageFactory == null) {
throw new NullPointerException("messageFactory");
@@ -216,51 +225,51 @@
this.messageFactory = messageFactory;
this.interestedIdleStatus = interestedIdleStatus;
- this.policy = policy;
+ requestTimeoutHandler = policy;
- setKeepAliveRequestInterval(keepAliveRequestInterval);
- setKeepAliveRequestTimeout(keepAliveRequestTimeout);
+ setRequestInterval(keepAliveRequestInterval);
+ setRequestTimeout(keepAliveRequestTimeout);
}
public IdleStatus getInterestedIdleStatus() {
return interestedIdleStatus;
}
- public KeepAlivePolicy getPolicy() {
- return policy;
+ public KeepAliveRequestTimeoutHandler getRequestTimeoutHandler() {
+ return requestTimeoutHandler;
}
- public void setPolicy(KeepAlivePolicy policy) {
- if (policy == null) {
- throw new NullPointerException("policy");
+ public void setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler timeoutHandler) {
+ if (timeoutHandler == null) {
+ throw new NullPointerException("timeoutHandler");
}
- this.policy = policy;
+ requestTimeoutHandler = timeoutHandler;
}
- public int getKeepAliveRequestInterval() {
- return keepAliveRequestInterval;
+ public int getRequestInterval() {
+ return requestInterval;
}
- public void setKeepAliveRequestInterval(int keepAliveRequestInterval) {
+ public void setRequestInterval(int keepAliveRequestInterval) {
if (keepAliveRequestInterval <= 0) {
throw new IllegalArgumentException(
"keepAliveRequestInterval must be a positive integer: " +
keepAliveRequestInterval);
}
- this.keepAliveRequestInterval = keepAliveRequestInterval;
+ requestInterval = keepAliveRequestInterval;
}
- public int getKeepAliveRequestTimeout() {
- return keepAliveRequestTimeout;
+ public int getRequestTimeout() {
+ return requestTimeout;
}
- public void setKeepAliveRequestTimeout(int keepAliveRequestTimeout) {
+ public void setRequestTimeout(int keepAliveRequestTimeout) {
if (keepAliveRequestTimeout <= 0) {
throw new IllegalArgumentException(
"keepAliveRequestTimeout must be a positive integer: " +
keepAliveRequestTimeout);
}
- this.keepAliveRequestTimeout = keepAliveRequestTimeout;
+ requestTimeout = keepAliveRequestTimeout;
}
public KeepAliveMessageFactory getMessageFactory() {
@@ -353,7 +362,7 @@
// If policy is OFF, there's no need to wait for
// the response.
- if (getPolicy() != KeepAlivePolicy.OFF) {
+ if (getRequestTimeoutHandler() != KeepAliveRequestTimeoutHandler.DEAF_SPEAKER) {
markStatus(session);
} else {
resetStatus(session);
@@ -363,7 +372,9 @@
handlePingTimeout(session);
}
} else if (status == IdleStatus.READER_IDLE) {
- handlePingTimeout(session);
+ if (session.containsAttribute(WAITING_FOR_RESPONSE)) {
+ handlePingTimeout(session);
+ }
}
if (forwardEvent) {
@@ -371,48 +382,27 @@
}
}
- private void handlePingTimeout(IoSession session) {
+ private void handlePingTimeout(IoSession session) throws Exception {
resetStatus(session);
- switch (getPolicy()) {
- case OFF:
- break;
- case LOG:
- logTimeout();
- break;
- case EXCEPTION:
- throw new KeepAliveTimeoutException(
- getTimeoutMessage());
- case CLOSE:
- logTimeout();
- session.close();
- break;
- default:
- throw new InternalError();
- }
- }
-
- private void logTimeout() {
- if (logger.isWarnEnabled()) {
- logger.warn(getTimeoutMessage());
+ KeepAliveRequestTimeoutHandler handler = getRequestTimeoutHandler();
+ if (handler == KeepAliveRequestTimeoutHandler.DEAF_SPEAKER) {
+ return;
}
- }
- private String getTimeoutMessage() {
- return "Keep-alive response message was not received within " +
- getKeepAliveRequestTimeout() + " second(s).";
+ handler.keepAliveRequestTimedOut(this, session);
}
private void markStatus(IoSession session) {
session.getConfig().setIdleTime(interestedIdleStatus, 0);
- session.getConfig().setIdleTime(
- IdleStatus.READER_IDLE, getKeepAliveRequestTimeout());
+ session.getConfig().setReaderIdleTime(getRequestTimeout());
session.setAttribute(WAITING_FOR_RESPONSE);
}
private void resetStatus(IoSession session) {
- session.getConfig().setIdleTime(IdleStatus.READER_IDLE, 0);
+ session.getConfig().setReaderIdleTime(0);
+ session.getConfig().setWriterIdleTime(0);
session.getConfig().setIdleTime(
- interestedIdleStatus, getKeepAliveRequestInterval());
+ interestedIdleStatus, getRequestInterval());
session.removeAttribute(WAITING_FOR_RESPONSE);
}
Added: mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java?rev=646276&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java Wed Apr 9 04:34:35 2008
@@ -0,0 +1,101 @@
+/*
+ * 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.mina.filter.keepalive;
+
+import org.apache.mina.common.IoSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tells {@link KeepAliveFilter} what to do when a keep-alive response message
+ * was not received within a certain timeout.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface KeepAliveRequestTimeoutHandler {
+ /**
+ * Do nothing.
+ */
+ static KeepAliveRequestTimeoutHandler NOOP = new KeepAliveRequestTimeoutHandler() {
+ public void keepAliveRequestTimedOut(
+ KeepAliveFilter filter, IoSession session) throws Exception {
+ // Do nothing.
+ }
+ };
+
+ /**
+ * Logs a warning message, but doesn't do anything else.
+ */
+ static KeepAliveRequestTimeoutHandler LOG = new KeepAliveRequestTimeoutHandler() {
+ private final Logger log =
+ LoggerFactory.getLogger(KeepAliveFilter.class);
+
+ public void keepAliveRequestTimedOut(
+ KeepAliveFilter filter, IoSession session) throws Exception {
+ log.warn("A keep-alive response message was not received within " +
+ "{} second(s).", filter.getRequestTimeout());
+ }
+ };
+
+ /**
+ * Throws a {@link KeepAliveTimeoutException}.
+ */
+ static KeepAliveRequestTimeoutHandler EXCEPTION = new KeepAliveRequestTimeoutHandler() {
+ public void keepAliveRequestTimedOut(
+ KeepAliveFilter filter, IoSession session) throws Exception {
+ throw new KeepAliveTimeoutException(
+ "A keep-alive response message was not received within " +
+ filter.getRequestTimeout() + " second(s).");
+ }
+ };
+
+ /**
+ * Closes the connection after logging.
+ */
+ static KeepAliveRequestTimeoutHandler CLOSE = new KeepAliveRequestTimeoutHandler() {
+ private final Logger log =
+ LoggerFactory.getLogger(KeepAliveFilter.class);
+
+ public void keepAliveRequestTimedOut(
+ KeepAliveFilter filter, IoSession session) throws Exception {
+ log.warn("Closing the session because a keep-alive response " +
+ "message was not received within {} second(s).",
+ filter.getRequestTimeout());
+ session.close();
+ }
+ };
+
+ /**
+ * A special handler for the 'deaf speaker' mode.
+ */
+ static KeepAliveRequestTimeoutHandler DEAF_SPEAKER = new KeepAliveRequestTimeoutHandler() {
+ public void keepAliveRequestTimedOut(
+ KeepAliveFilter filter, IoSession session) throws Exception {
+ throw new Error("Shouldn't be invoked. Please file a bug report.");
+ }
+ };
+
+ /**
+ * Invoked when {@link KeepAliveFilter} couldn't receive the response for
+ * the sent keep alive message.
+ */
+ void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception;
+}
Propchange: mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: mina/trunk/core/src/main/java/org/apache/mina/filter/keepalive/KeepAliveRequestTimeoutHandler.java
------------------------------------------------------------------------------
svn:keywords = Rev Date