package com.netflix.evcache.util;
import com.netflix.evcache.pool.ServerGroup;
import java.util.Iterator;
import java.util.Set;
/**
* A circular iterator for ReplicaSets. This ensures that all ReplicaSets are
* equal number of requests.
*
* @author smadappa
*/
public class ServerGroupCircularIterator {
private Entry<ServerGroup> entry;
private int size = 0;
/**
* Creates an instance of ReplicaSetCircularIterator across all ReplicaSets.
*
* @param allReplicaSets
* Set of all available ReplicaSets.
*/
public ServerGroupCircularIterator(Set<ServerGroup> allReplicaSets) {
if (allReplicaSets == null || allReplicaSets.isEmpty()) return;
Entry<ServerGroup> pEntry = null;
for (Iterator<ServerGroup> itr = allReplicaSets.iterator(); itr.hasNext();) {
size++;
final ServerGroup rSet = itr.next();
final Entry<ServerGroup> newEntry = new Entry<ServerGroup>(rSet, pEntry);
if (entry == null) entry = newEntry;
pEntry = newEntry;
}
/*
* Connect the first and the last entry to form a circular list
*/
if (pEntry != null) {
entry.next = pEntry;
}
}
/**
* Returns the next ReplicaSet which should get the request.
*
* @return - the next ReplicaSetCircularIterator in the iterator. If there
* are none then null is returned.
*/
public ServerGroup next() {
if (entry == null) return null;
entry = entry.next;
return entry.element;
}
/**
* Returns the next ReplicaSet excluding the given ReplicaSet which should
* get the request.
*
* @return - the next ReplicaSet in the iterator. If there are none then
* null is returned.
*/
public ServerGroup next(ServerGroup ignoreReplicaSet) {
if (entry == null) return null;
entry = entry.next;
if (entry.element.equals(ignoreReplicaSet)) {
return entry.next.element;
} else {
return entry.element;
}
}
public int getSize() {
return size;
}
/**
* The Entry keeps track of the current element and next element in the
* list.
*
* @author smadappa
*
* @param <E>
*/
static class Entry<E> {
private E element;
private Entry<E> next;
/**
* Creates an instance of Entry.
*/
Entry(E element, Entry<E> next) {
this.element = element;
this.next = next;
}
}
public String toString() {
final StringBuilder current = new StringBuilder();
if (entry != null) {
Entry<ServerGroup> startEntry = entry;
current.append(startEntry.element);
while (!entry.next.equals(startEntry)) {
current.append(",").append(entry.next.element);
entry = entry.next;
}
}
return "Server Group Iterator : { size=" + getSize() + "; Server Group=" + current.toString() + "}";
}
}