package ibis.ipl.registry.gossip;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ARRGCache {
private static final Logger logger = LoggerFactory.getLogger(ARRGCache.class);
private final int cacheSize;
private final Random random;
private final ArrayList<ARRGCacheEntry> cache;
public ARRGCache(int cacheSize) {
this.cacheSize = cacheSize;
cache = new ArrayList<ARRGCacheEntry>();
random = new Random();
}
public synchronized ARRGCacheEntry[] getRandomEntries(int n, boolean includeArrgOnly) {
List<ARRGCacheEntry> result = new ArrayList<ARRGCacheEntry>();
BitSet selected = new BitSet();
while (selected.cardinality() < n && selected.cardinality() < cache.size()) {
int next = random.nextInt(cache.size());
selected.set(next);
ARRGCacheEntry entry = cache.get(next);
if (includeArrgOnly || !entry.isArrgOnly()) {
result.add(entry);
}
}
return result.toArray(new ARRGCacheEntry[0]);
}
public synchronized ARRGCacheEntry getRandomEntry(boolean includeArrgOnly) {
ARRGCacheEntry[] result = getRandomEntries(1, includeArrgOnly);
if (result.length < 1) {
return null;
}
return result[0];
}
public synchronized void add(ARRGCacheEntry... entries) {
//add entries
for (ARRGCacheEntry entry : entries) {
if (entry != null) {
cache.add(entry);
}
}
//purge duplicates
for (int i = 0; i < cache.size(); i++) {
for (int j = i + 1; j < cache.size(); j++) {
if (cache.get(i).sameAddressAs(cache.get(j))) {
cache.remove(j);
j--;
}
}
}
//remove random entries if cache outgrew maximum value
while(cache.size() > cacheSize) {
cache.remove(random.nextInt(cache.size()));
}
logger.debug("cache value now: " + cache.size());
}
public synchronized ARRGCacheEntry[] getEntries(boolean includeArrgOnly) {
if (includeArrgOnly) {
return cache.toArray(new ARRGCacheEntry[0]);
} else {
ArrayList<ARRGCacheEntry> result = new ArrayList<ARRGCacheEntry>();
for (ARRGCacheEntry entry: cache) {
if (!entry.isArrgOnly()) {
result.add(entry);
}
}
return result.toArray(new ARRGCacheEntry[0]);
}
}
}