blob: c930842a0dc80803789b183931435cf19a2845d4 [file] [log] [blame]
/*
* 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.geode.internal.admin.remote;
import org.apache.geode.distributed.internal.DistributionMessage;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.ReplyException;
import org.apache.geode.distributed.internal.ReplyProcessor21;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
/**
* A <code>ReplyProcessor</code> that is used by an {@link AdminRequest} to wait for an
* {@link AdminResponse}. If
* {@link org.apache.geode.distributed.internal.ReplyProcessor21#waitForReplies()} returns saying
* that we didn't time out and there is no response, it means that the member for which we were
* awaiting a response has left the distributed system. This helps us fix bug 31562.
*
* <P>
*
* An <code>AdminReplyProcessor</code> can be {@linkplain #cancel cancelled}.
*
* @since GemFire 4.0
*/
class AdminReplyProcessor extends ReplyProcessor21 {
/** The response to the <code>AdminRequest</code>. */
private volatile AdminResponse response;
/**
* The thread that is waiting for replies. We need this thread so that we can interrupt it when
* this processor is cancelled.
*/
private volatile Thread thread;
/** Has this reply processor been cancelled? */
private volatile boolean isCancelled;
/** The member from whom we expect a response */
private final InternalDistributedMember responder;
////////////////////// Constructors //////////////////////
/**
* Creates a new <code>AdminReplyProcessor</code> that waits for a reply from the given member of
* the distributed system. Note that <code>AdminRequest</code>s are only sent to one member of the
* distributed system.
*/
AdminReplyProcessor(InternalDistributedSystem system, InternalDistributedMember member) {
super(system, member);
this.isCancelled = false;
this.responder = member;
}
////////////////////// Instance Methods //////////////////////
/**
* Keep track of the <code>AdminResponse</code> we received.
*/
@Override
public void process(DistributionMessage message) {
try {
this.response = (AdminResponse) message;
} finally {
super.process(message);
}
}
/**
* Since we can't override <code>waitForReplies</code>, we have to get the thread that is waiting
* in <code>preWait</code>.
*/
@Override
protected void preWait() {
this.thread = Thread.currentThread();
super.preWait();
}
/**
* "Cancels" this reply processor by instructing the thread that is waiting for replies that it
* shouldn't wait any more.
*/
public void cancel() {
this.isCancelled = true;
if (this.thread != null) {
this.thread.interrupt();
}
}
/**
* If we are interrupted after we are cancelled, return <code>true</code> indicating that there is
* a "response". That way, we won't complain about timing out. However, the response is still
* <code>null</code>.
*
* <P>
*
* Otherwise, re-throw the <code>InterruptedException</code>.
*/
protected boolean handleInterruption(InterruptedException ie, long msecsRemaining)
throws InterruptedException, ReplyException {
if (Thread.interrupted())
throw new InterruptedException();
if (this.isCancelled) {
return true;
} else {
throw ie;
}
}
/**
* Returns the response that this processor has been waiting for. If this method returns
* <code>null</code> and <code>waitForReplies</code> return <code>true</code>, it means that the
* request was cancelled. If this method returns <code>null</code> and <code>waitForReplies</code>
* return <code>false</code>, it means that <code>waitForReplies</code> timed out.
*/
public AdminResponse getResponse() {
return this.response;
}
/**
* Returns the member who we are waiting to send us a response.
*/
public InternalDistributedMember getResponder() {
return this.responder;
}
}