/* * 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; /** * Abstract cancellation proxy for cancelling an operation, esp. a thread. * * Creators of services or threads should implement a subclass of CancelCriterion, and implement the * two methods - cancelInProgress, and generateCancelledException(e). * * Code inside the service can check to see if the service is cancelled by calling * {@link #checkCancelInProgress(Throwable)}. Generally the pattern is to check before performing an * operation, check if the service is canceled before propgrating an exception futher up the stack, * and check for cancelation inside a long loop. Eg. * * <code> * while(true) { * c.checkCancelInProgress(null); * try { * dispatchEvents(); * } catch(IOException e) { * c.checkCancelInProgress(e); * throw e; * } * } * </code> * * @see CancelException * @since GemFire 5.1 */ public abstract class CancelCriterion { /** * Indicate if the service is in the progress of being cancelled. The typical use of this is to * indicate, in the case of an {@link InterruptedException}, that the current operation should be * cancelled. * * @return null if the service is not shutting down, or a message that can be used to construct an * exception indicating the service is shut down. */ public abstract String cancelInProgress(); // import org.apache.geode.distributed.internal.DistributionManager; // * <p> // * In particular, a {@link DistributionManager} returns a non-null result if // * message distribution has been terminated. /** * Use this utility function in your implementation of cancelInProgress() and cancelled() to * indicate a system failure * * @return failure string if system failure has occurred */ protected final String checkFailure() { Throwable tilt = SystemFailure.getFailure(); if (tilt != null) { // Allocate no objects here! return SystemFailure.JVM_CORRUPTION; } return null; } /** * See if the current operation is being cancelled. If so, it either throws a * {@link RuntimeException} (usually a {@link CancelException}). * * @param e an underlying exception or null if there is no exception that triggered this check * @see #cancelInProgress() */ public final void checkCancelInProgress(Throwable e) { SystemFailure.checkFailure(); String reason = cancelInProgress(); if (reason == null) { return; } throw generateCancelledException(e); } /** * Template factory method for generating the exception to be thrown by * {@link #checkCancelInProgress(Throwable)}. Override this to specify different exception for * checkCancelInProgress() to throw. * * This method should wrap the exception in a service specific CancelationException (eg * CacheClosedException). or return null if the service is not being canceled. * * @param e an underlying exception, if any * @return RuntimeException to be thrown by checkCancelInProgress(), null if the receiver has not * been cancelled. */ abstract public RuntimeException generateCancelledException(Throwable e); /** * Checks to see if a cancellation is in progress. This is equivalent to the expression * (cancelInProgress() != null). * * @return true if a cancellation is in progress, false if not */ public boolean isCancelInProgress() { return cancelInProgress() != null; } }