/*
 *
 * Copyright 2013 Netflix, Inc.
 *
 * Licensed 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.
 *
 */
package com.netflix.loadbalancer;

import java.util.List;
import java.util.Random;

import com.netflix.client.config.IClientConfig;

/**
 * A loadbalacing strategy that randomly distributes traffic amongst existing
 * servers.
 * 
 * @author stonse
 * 
 */
public class RandomRule extends AbstractLoadBalancerRule {
    Random rand;

    public RandomRule() {
        rand = new Random();
    }

    /**
     * Randomly choose from all living servers
     */
    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                /*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 */
                return null;
            }

            int index = rand.nextInt(serverCount);
            server = upList.get(index);

            if (server == null) {
                /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }

        return server;

    }

	@Override
	public Server choose(Object key) {
		return choose(getLoadBalancer(), key);
	}

	@Override
	public void initWithNiwsConfig(IClientConfig clientConfig) {
		// TODO Auto-generated method stub
		
	}
}

@@ -657,25 +657,52 @@
 ort 
-java.util.List
+com.netflix.client.config.IClientConfig
 ;%0D%0A
+%0D%0A
 impo
@@ -718,65 +718,60 @@
 til.
-Random
+List
 ;%0D%0A
-%0D%0A
 import 
-com.netflix.client.config.IClientConfig
+java.util.concurrent.ThreadLocalRandom
 ;%0D%0A%0D
@@ -965,92 +965,8 @@
 e %7B%0D
-%0A    Random rand;%0D%0A%0D%0A    public RandomRule() %7B%0D%0A        rand = new Random();%0D%0A    %7D%0D
 %0A%0D%0A 
@@ -1857,17 +1857,20 @@
 x = 
-rand.next
+chooseRandom
 Int(
@@ -2535,24 +2535,153 @@
 %0A%0D%0A    %7D%0D%0A%0D%0A
+    protected int chooseRandomInt(int serverCount) %7B%0D%0A        return ThreadLocalRandom.current().nextInt(serverCount);%0D%0A    %7D%0D%0A%0D%0A
 %09@Override%0D%0A

Change RandomRule to use a ThreadLocalRandom instead of Random, as a perf optimization