/* * 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. */ using System; namespace Apache.NMS.Policies { /// /// A policy used to customize exactly how you want the redelivery to work. /// public class RedeliveryPolicy : IRedeliveryPolicy { private static readonly object syncObject = new object(); private double collisionAvoidanceFactor = .15; private int initialRedeliveryDelay = 1000; private int maximumRedeliveries = 6; private int backOffMultiplier = 5; private bool useCollisionAvoidance = false; private bool useExponentialBackOff = false; private static Random randomNumberGenerator; private static bool nextBool = false; #region IRedeliveryPolicy Members public int CollisionAvoidancePercent { get { return Convert.ToInt32(Math.Round(collisionAvoidanceFactor * 100)); } set { collisionAvoidanceFactor = Convert.ToDouble(value) * .01; } } public bool UseCollisionAvoidance { get { return this.useCollisionAvoidance; } set { this.useCollisionAvoidance = value; } } public int InitialRedeliveryDelay { get { return this.initialRedeliveryDelay; } set { this.initialRedeliveryDelay = value; } } public int MaximumRedeliveries { get { return this.maximumRedeliveries; } set { this.maximumRedeliveries = value; } } public virtual int RedeliveryDelay(int redeliveredCounter) { int delay = 0; if(redeliveredCounter == 0) { // The first time through there is no delay, the Rollback should be immediate. return 0; } if(UseExponentialBackOff && BackOffMultiplier > 1) { delay = initialRedeliveryDelay * Convert.ToInt32(Math.Pow(BackOffMultiplier, redeliveredCounter - 1)); } else { delay = InitialRedeliveryDelay; } if(UseCollisionAvoidance) { Random random = RandomNumberGenerator; double variance = (NextBool ? collisionAvoidanceFactor : collisionAvoidanceFactor *= -1) * random.NextDouble(); delay += Convert.ToInt32(Convert.ToDouble(delay) * variance); } return delay; } public bool UseExponentialBackOff { get { return this.useExponentialBackOff; } set { this.useExponentialBackOff = value; } } public int BackOffMultiplier { get { return backOffMultiplier; } set { backOffMultiplier = value; } } #endregion /// /// Gets the random number generator. /// /// The random number generator. protected static Random RandomNumberGenerator { get { if(randomNumberGenerator == null) { lock(syncObject) { if(randomNumberGenerator == null) { randomNumberGenerator = new Random(DateTime.Now.Second); } } } return randomNumberGenerator; } } /// /// Gets the next boolean /// /// true if [next bool]; otherwise, false. protected static bool NextBool { get { lock(syncObject) { nextBool = !nextBool; return nextBool; } } } /// /// Clone this object and return a new instance that the caller now owns. /// public Object Clone() { // Since we are a derived class use the base's Clone() // to perform the shallow copy. Since it is shallow it // will include our derived class. Since we are derived, // this method is an override. return this.MemberwiseClone(); } } }