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