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     * @version $Revision: 1.11 $
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 initialRedeliveryDelay = 1000L;
038        private boolean useCollisionAvoidance;
039        private boolean useExponentialBackOff;
040        private double backOffMultiplier = 5.0;
041    
042        public RedeliveryPolicy() {
043        }
044    
045        public RedeliveryPolicy copy() {
046            try {
047                return (RedeliveryPolicy)clone();
048            } catch (CloneNotSupportedException e) {
049                throw new RuntimeException("Could not clone: " + e, e);
050            }
051        }
052    
053        public double getBackOffMultiplier() {
054            return backOffMultiplier;
055        }
056    
057        public void setBackOffMultiplier(double backOffMultiplier) {
058            this.backOffMultiplier = backOffMultiplier;
059        }
060    
061        public short getCollisionAvoidancePercent() {
062            return (short)Math.round(collisionAvoidanceFactor * 100);
063        }
064    
065        public void setCollisionAvoidancePercent(short collisionAvoidancePercent) {
066            this.collisionAvoidanceFactor = collisionAvoidancePercent * 0.01d;
067        }
068    
069        public long getInitialRedeliveryDelay() {
070            return initialRedeliveryDelay;
071        }
072    
073        public void setInitialRedeliveryDelay(long initialRedeliveryDelay) {
074            this.initialRedeliveryDelay = initialRedeliveryDelay;
075        }
076    
077        public int getMaximumRedeliveries() {
078            return maximumRedeliveries;
079        }
080    
081        public void setMaximumRedeliveries(int maximumRedeliveries) {
082            this.maximumRedeliveries = maximumRedeliveries;
083        }
084    
085        public long getRedeliveryDelay(long previousDelay) {
086            long redeliveryDelay;
087    
088            if (previousDelay == 0) {
089                redeliveryDelay = initialRedeliveryDelay;
090            } else if (useExponentialBackOff && backOffMultiplier > 1) {
091                redeliveryDelay = (long) (previousDelay * backOffMultiplier);
092            } else {
093                redeliveryDelay = previousDelay;
094            }
095    
096            if (useCollisionAvoidance) {
097                /*
098                 * First random determines +/-, second random determines how far to
099                 * go in that direction. -cgs
100                 */
101                Random random = getRandomNumberGenerator();
102                double variance = (random.nextBoolean() ? collisionAvoidanceFactor : -collisionAvoidanceFactor) * random.nextDouble();
103                redeliveryDelay += redeliveryDelay * variance;
104            }
105    
106            return redeliveryDelay;
107        }
108    
109        public boolean isUseCollisionAvoidance() {
110            return useCollisionAvoidance;
111        }
112    
113        public void setUseCollisionAvoidance(boolean useCollisionAvoidance) {
114            this.useCollisionAvoidance = useCollisionAvoidance;
115        }
116    
117        public boolean isUseExponentialBackOff() {
118            return useExponentialBackOff;
119        }
120    
121        public void setUseExponentialBackOff(boolean useExponentialBackOff) {
122            this.useExponentialBackOff = useExponentialBackOff;
123        }
124    
125        protected static synchronized Random getRandomNumberGenerator() {
126            if (randomNumberGenerator == null) {
127                randomNumberGenerator = new Random();
128            }
129            return randomNumberGenerator;
130        }
131    
132    }