/*
* Copyright 2015 jonathan.colt.
*
* 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.jivesoftware.os.amza.client.http;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jivesoftware.os.amza.api.ring.RingMember;
import com.jivesoftware.os.amza.api.ring.RingMemberAndHost;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
*
* @author jonathan.colt
*/
public class Ring {
private static final Random RANDOM = new Random(); // Random number generator
private final int leaderIndex;
final RingMemberAndHost[] members;
public Ring(int leaderIndex, RingMemberAndHost[] members) {
this.leaderIndex = leaderIndex;
this.members = members;
}
public RingMemberAndHost leader() {
return (leaderIndex == -1) ? null : members[leaderIndex];
}
public RingMemberAndHost[] actualRing() {
return members;
}
public RingMemberAndHost[] orderedRing(List<RingMember> membersInOrder) {
List<RingMemberAndHost> ordered = Lists.newArrayListWithCapacity(members.length);
if (membersInOrder == null) {
if (leaderIndex >= 0) {
ordered.add(members[leaderIndex]);
}
for (int i = 0; i < members.length; i++) {
if (i != leaderIndex) {
ordered.add(members[i]);
}
}
} else {
Map<RingMember, RingMemberAndHost> memberHosts = Maps.newHashMapWithExpectedSize(members.length);
for (RingMemberAndHost member : members) {
memberHosts.put(member.ringMember, member);
}
for (RingMember ringMember : membersInOrder) {
RingMemberAndHost ringMemberAndHost = memberHosts.remove(ringMember);
if (ringMemberAndHost != null) {
ordered.add(ringMemberAndHost);
}
}
for (RingMemberAndHost ringMemberAndHost : memberHosts.values()) {
ordered.add(ringMemberAndHost);
}
}
return ordered.toArray(new RingMemberAndHost[0]);
}
public RingMemberAndHost[] leaderlessRing() {
if (leaderIndex == -1) {
return Arrays.copyOf(members, members.length);
} else {
RingMemberAndHost[] memberAndHosts = new RingMemberAndHost[members.length - 1];
System.arraycopy(members, 0, memberAndHosts, 0, leaderIndex);
System.arraycopy(members, leaderIndex + 1, memberAndHosts, leaderIndex, members.length - 1 - leaderIndex);
return memberAndHosts;
}
}
public RingMemberAndHost[] randomizeRing() {
RingMemberAndHost[] array = Arrays.copyOf(members, members.length);
for (int i = 0; i < array.length; i++) {
int randomPosition = RANDOM.nextInt(array.length);
RingMemberAndHost temp = array[i];
array[i] = array[randomPosition];
array[randomPosition] = temp;
}
return array;
}
}