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; 018 019import java.io.Serializable; 020import java.util.Random; 021import org.apache.activemq.filter.DestinationMapEntry; 022import org.apache.activemq.util.IntrospectionSupport; 023 024/** 025 * Configuration options for a messageConsumer used to control how messages are re-delivered when they 026 * are rolled back. 027 * May be used server side on a per destination basis via the Broker RedeliveryPlugin 028 * 029 * @org.apache.xbean.XBean element="redeliveryPolicy" 030 * 031 */ 032public class RedeliveryPolicy extends DestinationMapEntry implements Cloneable, Serializable { 033 034 public static final int NO_MAXIMUM_REDELIVERIES = -1; 035 public static final int DEFAULT_MAXIMUM_REDELIVERIES = 6; 036 037 private static Random randomNumberGenerator; 038 039 // +/-15% for a 30% spread -cgs 040 protected double collisionAvoidanceFactor = 0.15d; 041 protected int maximumRedeliveries = DEFAULT_MAXIMUM_REDELIVERIES; 042 protected long maximumRedeliveryDelay = -1; 043 protected long initialRedeliveryDelay = 1000L; 044 protected boolean useCollisionAvoidance; 045 protected boolean useExponentialBackOff; 046 protected double backOffMultiplier = 5.0; 047 protected long redeliveryDelay = initialRedeliveryDelay; 048 049 public RedeliveryPolicy() { 050 } 051 052 public RedeliveryPolicy copy() { 053 try { 054 return (RedeliveryPolicy)clone(); 055 } catch (CloneNotSupportedException e) { 056 throw new RuntimeException("Could not clone: " + e, e); 057 } 058 } 059 060 public double getBackOffMultiplier() { 061 return backOffMultiplier; 062 } 063 064 public void setBackOffMultiplier(double backOffMultiplier) { 065 this.backOffMultiplier = backOffMultiplier; 066 } 067 068 public short getCollisionAvoidancePercent() { 069 return (short)Math.round(collisionAvoidanceFactor * 100); 070 } 071 072 public void setCollisionAvoidancePercent(short collisionAvoidancePercent) { 073 this.collisionAvoidanceFactor = collisionAvoidancePercent * 0.01d; 074 } 075 076 public long getInitialRedeliveryDelay() { 077 return initialRedeliveryDelay; 078 } 079 080 public void setInitialRedeliveryDelay(long initialRedeliveryDelay) { 081 this.initialRedeliveryDelay = initialRedeliveryDelay; 082 } 083 084 public long getMaximumRedeliveryDelay() { 085 return maximumRedeliveryDelay; 086 } 087 088 public void setMaximumRedeliveryDelay(long maximumRedeliveryDelay) { 089 this.maximumRedeliveryDelay = maximumRedeliveryDelay; 090 } 091 092 public int getMaximumRedeliveries() { 093 return maximumRedeliveries; 094 } 095 096 public void setMaximumRedeliveries(int maximumRedeliveries) { 097 this.maximumRedeliveries = maximumRedeliveries; 098 } 099 100 public long getNextRedeliveryDelay(long previousDelay) { 101 long nextDelay = redeliveryDelay; 102 103 if (previousDelay > 0 && useExponentialBackOff && backOffMultiplier > 1) { 104 nextDelay = (long) (previousDelay * backOffMultiplier); 105 if(maximumRedeliveryDelay != -1 && nextDelay > maximumRedeliveryDelay) { 106 // in case the user made max redelivery delay less than redelivery delay for some reason. 107 nextDelay = Math.max(maximumRedeliveryDelay, redeliveryDelay); 108 } 109 } 110 111 if (useCollisionAvoidance) { 112 /* 113 * First random determines +/-, second random determines how far to 114 * go in that direction. -cgs 115 */ 116 Random random = getRandomNumberGenerator(); 117 double variance = (random.nextBoolean() ? collisionAvoidanceFactor : -collisionAvoidanceFactor) * random.nextDouble(); 118 nextDelay += nextDelay * variance; 119 } 120 121 return nextDelay; 122 } 123 124 public boolean isUseCollisionAvoidance() { 125 return useCollisionAvoidance; 126 } 127 128 public void setUseCollisionAvoidance(boolean useCollisionAvoidance) { 129 this.useCollisionAvoidance = useCollisionAvoidance; 130 } 131 132 public boolean isUseExponentialBackOff() { 133 return useExponentialBackOff; 134 } 135 136 public void setUseExponentialBackOff(boolean useExponentialBackOff) { 137 this.useExponentialBackOff = useExponentialBackOff; 138 } 139 140 protected static synchronized Random getRandomNumberGenerator() { 141 if (randomNumberGenerator == null) { 142 randomNumberGenerator = new Random(); 143 } 144 return randomNumberGenerator; 145 } 146 147 public void setRedeliveryDelay(long redeliveryDelay) { 148 this.redeliveryDelay = redeliveryDelay; 149 } 150 151 public long getRedeliveryDelay() { 152 return redeliveryDelay; 153 } 154 155 @Override 156 public String toString() { 157 return IntrospectionSupport.toString(this, DestinationMapEntry.class, null); 158 } 159}