001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2010 Sun Microsystems, Inc.
025 *      Portions copyright 2013 ForgeRock AS.
026 */
027
028package org.forgerock.opendj.ldap;
029
030import java.util.Collection;
031import java.util.concurrent.ScheduledExecutorService;
032import java.util.concurrent.TimeUnit;
033
034/**
035 * A fail-over load balancing algorithm provides fault tolerance across multiple
036 * underlying connection factories.
037 * <p>
038 * This algorithm is typically used for load-balancing <i>between</i> data
039 * centers, where there is preference to always forward connection requests to
040 * the <i>closest available</i> data center. This algorithm contrasts with the
041 * {@link RoundRobinLoadBalancingAlgorithm} which is used for load-balancing
042 * <i>within</i> a data center.
043 * <p>
044 * This algorithm selects connection factories based on the order in which they
045 * were provided during construction. More specifically, an attempt to obtain a
046 * connection factory will always return the <i>first operational</i> connection
047 * factory in the list. Applications should, therefore, organize the connection
048 * factories such that the <i>preferred</i> (usually the closest) connection
049 * factories appear before those which are less preferred.
050 * <p>
051 * If a problem occurs that temporarily prevents connections from being obtained
052 * for one of the connection factories, then this algorithm automatically
053 * "fails over" to the next operational connection factory in the list. If none
054 * of the connection factories are operational then a
055 * {@code ConnectionException} is returned to the client.
056 * <p>
057 * The implementation periodically attempts to connect to failed connection
058 * factories in order to determine if they have become available again.
059 *
060 * @see RoundRobinLoadBalancingAlgorithm
061 * @see Connections#newLoadBalancer(LoadBalancingAlgorithm)
062 */
063public final class FailoverLoadBalancingAlgorithm extends AbstractLoadBalancingAlgorithm {
064
065    /**
066     * Creates a new fail-over load balancing algorithm which will monitor
067     * offline connection factories every 1 second using the default scheduler.
068     *
069     * @param factories
070     *            The ordered collection of connection factories.
071     */
072    public FailoverLoadBalancingAlgorithm(final Collection<? extends ConnectionFactory> factories) {
073        this(factories, null, 1, TimeUnit.SECONDS, null);
074    }
075
076    /**
077     * Creates a new fail-over load balancing algorithm which will monitor
078     * offline connection factories every 1 second using the default scheduler.
079     *
080     * @param factories
081     *            The ordered collection of connection factories.
082     * @param listener
083     *            The event listener which should be notified whenever a
084     *            connection factory changes state from online to offline or
085     *            vice-versa.
086     */
087    public FailoverLoadBalancingAlgorithm(final Collection<? extends ConnectionFactory> factories,
088            final LoadBalancerEventListener listener) {
089        this(factories, listener, 1, TimeUnit.SECONDS, null);
090    }
091
092    /**
093     * Creates a new fail-over load balancing algorithm which will monitor
094     * offline connection factories using the specified frequency using the
095     * default scheduler.
096     *
097     * @param factories
098     *            The connection factories.
099     * @param listener
100     *            The event listener which should be notified whenever a
101     *            connection factory changes state from online to offline or
102     *            vice-versa.
103     * @param interval
104     *            The interval between attempts to poll offline factories.
105     * @param unit
106     *            The time unit for the interval between attempts to poll
107     *            offline factories.
108     */
109    public FailoverLoadBalancingAlgorithm(final Collection<? extends ConnectionFactory> factories,
110            final LoadBalancerEventListener listener, final long interval, final TimeUnit unit) {
111        this(factories, listener, interval, unit, null);
112    }
113
114    /**
115     * Creates a new fail-over load balancing algorithm which will monitor
116     * offline connection factories using the specified frequency and scheduler.
117     *
118     * @param factories
119     *            The connection factories.
120     * @param listener
121     *            The event listener which should be notified whenever a
122     *            connection factory changes state from online to offline or
123     *            vice-versa.
124     * @param interval
125     *            The interval between attempts to poll offline factories.
126     * @param unit
127     *            The time unit for the interval between attempts to poll
128     *            offline factories.
129     * @param scheduler
130     *            The scheduler which should for periodically monitoring dead
131     *            connection factories to see if they are usable again.
132     */
133    public FailoverLoadBalancingAlgorithm(final Collection<? extends ConnectionFactory> factories,
134            final LoadBalancerEventListener listener, final long interval, final TimeUnit unit,
135            final ScheduledExecutorService scheduler) {
136        super(factories, listener, interval, unit, scheduler);
137    }
138
139    /**
140     * Creates a new fail-over load balancing algorithm which will monitor
141     * offline connection factories using the specified frequency using the
142     * default scheduler.
143     *
144     * @param factories
145     *            The connection factories.
146     * @param interval
147     *            The interval between attempts to poll offline factories.
148     * @param unit
149     *            The time unit for the interval between attempts to poll
150     *            offline factories.
151     */
152    public FailoverLoadBalancingAlgorithm(final Collection<? extends ConnectionFactory> factories,
153            final long interval, final TimeUnit unit) {
154        this(factories, null, interval, unit, null);
155    }
156
157    /**
158     * Creates a new fail-over load balancing algorithm which will monitor
159     * offline connection factories using the specified frequency and scheduler.
160     *
161     * @param factories
162     *            The connection factories.
163     * @param interval
164     *            The interval between attempts to poll offline factories.
165     * @param unit
166     *            The time unit for the interval between attempts to poll
167     *            offline factories.
168     * @param scheduler
169     *            The scheduler which should for periodically monitoring dead
170     *            connection factories to see if they are usable again.
171     */
172    public FailoverLoadBalancingAlgorithm(final Collection<? extends ConnectionFactory> factories,
173            final long interval, final TimeUnit unit, final ScheduledExecutorService scheduler) {
174        this(factories, null, interval, unit, scheduler);
175    }
176
177    /** {@inheritDoc} */
178    @Override
179    String getAlgorithmName() {
180        return "Failover";
181    }
182
183    /** {@inheritDoc} */
184    @Override
185    int getInitialConnectionFactoryIndex() {
186        // Always start with the first connection factory.
187        return 0;
188    }
189
190}