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