package net.jxta.impl.cm; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.concurrent.CountDownLatch; import net.jxta.id.IDFactory; import net.jxta.impl.cm.SrdiIndex.Entry; import net.jxta.peer.PeerID; import net.jxta.peergroup.PeerGroupID; /** * Load testing class that randomises it's calls to the index. */ public class IndexRandomLoadTester implements Runnable { public static final String[] ATTRIBUTES = { "alfa", "bravo", "charlie", "delta", "echo", "foxtrot" }; private final SrdiIndex index; private final int numOps; private boolean successful = false; private Map<String,Set<PeerID>> expectedPeersForAttribute; private Queue<PeerID> peerIds; private CountDownLatch completionLatch; public IndexRandomLoadTester(SrdiIndex index, int numOps, CountDownLatch completionLatch) { this.index = index; this.numOps = numOps; this.completionLatch = completionLatch; expectedPeersForAttribute = new HashMap<String, Set<PeerID>>(); peerIds = new LinkedList<PeerID>(); for(String attribute : ATTRIBUTES) { expectedPeersForAttribute.put(attribute, new HashSet<PeerID>()); } } public void run() { try { for(int i=0; i < numOps; i++) { double decider = Math.random(); /* decision on which operation to call here is randomised, * with a 49% chance of an add, 49% chance of a removing a peer, * and 2% chance of a clearing everything */ if(decider < 0.49) { String attribute = ATTRIBUTES[(int)Math.floor(Math.random() * ATTRIBUTES.length)]; PeerID peerId = IDFactory.newPeerID(PeerGroupID.defaultNetPeerGroupID); peerIds.add(peerId); expectedPeersForAttribute.get(attribute).add(peerId); index.add("x", attribute, "y", peerId, Long.MAX_VALUE); } else if (decider < 0.98) { PeerID peerIdToRemove = peerIds.poll(); if(peerIdToRemove != null) { for(String attr : ATTRIBUTES) { removeExpectedPeerForAttribute(attr, peerIdToRemove); } index.remove(peerIdToRemove); index.garbageCollect(); } } else { peerIds.clear(); for(String attribute : ATTRIBUTES) { expectedPeersForAttribute.get(attribute).clear(); } index.clear(); } /* after a mutation operation, we check the state of the index * still matches what we expect */ for(String attribute : ATTRIBUTES) { List<Entry> results = index.getRecord("x", attribute, "y"); Set<PeerID> resultPeers = new HashSet<PeerID>(); for(Entry e : results) { resultPeers.add(e.peerid); } Set<PeerID> expectedPeers = expectedPeersForAttribute.get(attribute); if(!resultPeers.containsAll(expectedPeers) || resultPeers.size() != expectedPeers.size()) { System.err.println("index does not match expected state: " + expectedPeers + " vs " + resultPeers); complete(false); return; } } } complete(true); } catch(Throwable t) { System.err.println("Thread died"); t.printStackTrace(); complete(false); } } private void complete(boolean success) { this.successful = success; completionLatch.countDown(); } public boolean isSuccessful() { return successful; } private void removeExpectedPeerForAttribute(String attribute, PeerID peerIdToRemove) { expectedPeersForAttribute.get(attribute).remove(peerIdToRemove); } }