package net.jxta.impl.cm; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; import net.jxta.document.AdvertisementFactory; import net.jxta.id.IDFactory; import net.jxta.peergroup.PeerGroupID; import net.jxta.protocol.PeerAdvertisement; /** * Load testing class that randomises it's calls to the index. */ public class CmRandomLoadTester implements Runnable { public static final String[] DIRECTORIES = { "alfa", "bravo", "charlie", "delta", "echo", "foxtrot" }; public static final String[] PEER_NAMES = { "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra" }; private final Cm advCache; private final int numOps; private boolean successful = false; private CountDownLatch completionLatch; private Map<String, Integer> expectedCounts; private Map<String, Set<String>> expectedFilesInDirectory; private Map<String, Map<String, Integer>> expectedPeersInDirectory; private Map<String, String> peerNameForDnAndFn; public CmRandomLoadTester(Cm advCache, int numOps, CountDownLatch completionLatch) { this.advCache = advCache; this.numOps = numOps; this.completionLatch = completionLatch; expectedCounts = new HashMap<String, Integer>(); expectedFilesInDirectory = new HashMap<String, Set<String>>(); expectedPeersInDirectory = new HashMap<String, Map<String, Integer>>(); peerNameForDnAndFn = new HashMap<String, String>(); for(String dn : DIRECTORIES) { expectedCounts.put(dn, 0); expectedFilesInDirectory.put(dn, new HashSet<String>()); HashMap<String, Integer> peerMap = new HashMap<String, Integer>(); expectedPeersInDirectory.put(dn, peerMap); for(String peerName : PEER_NAMES) { peerMap.put(peerName, 0); } } } public void run() { try { for(int i=0; i < numOps; i++) { if(Math.random() < 0.8) { // save peer String dn = randomDirectory(); String fn = randomFile(); String peerName = randomPeerName(); add(dn, fn, peerName); } else { // remove ArrayList<String> directories = new ArrayList<String>(); Collections.addAll(directories, DIRECTORIES); String dn = null; String fn = null; while(fn == null && directories.size() > 0) { dn = randomSelection(directories); fn = randomFileInDirectory(dn); } if(fn != null) { remove(dn, fn); } } /* after a mutation operation, we check the state of the index * still matches what we expect */ for(String directoryName : DIRECTORIES) { List<InputStream> records = advCache.getRecords(directoryName, Cm.NO_THRESHOLD, null); if(records.size() != expectedCounts.get(directoryName)) { System.err.println("Number of records turned for directory query did not match expected"); complete(false); return; } for(String fileName : expectedFilesInDirectory.get(directoryName)) { if(advCache.getInputStream(directoryName, fileName) == null) { System.err.println("Missing file within directory"); complete(false); return; } } } String searchDn = randomDirectory(); String searchPeerName = randomPeerName(); if(advCache.search(searchDn, "Name", searchPeerName, Cm.NO_THRESHOLD, null).size() != getExpectedPeerCount(searchDn, searchPeerName)) { System.err.println("Did not get expected number of results for name query"); complete(false); return; } } complete(true); } catch(Throwable t) { System.err.println("Thread died"); t.printStackTrace(); complete(false); } } private void add(String dn, String fn, String peerName) throws IOException { PeerAdvertisement adv = createPeerAdvert(PeerGroupID.defaultNetPeerGroupID, peerName); expectedCounts.put(dn, expectedCounts.get(dn)+1); expectedFilesInDirectory.get(dn).add(fn); modifyPeerNameCount(dn, peerName, +1); peerNameForDnAndFn.put(dn+'/'+fn, peerName); advCache.save(dn, fn, adv); } private void remove(String dn, String fn) throws IOException { expectedFilesInDirectory.get(dn).remove(fn); expectedCounts.put(dn, expectedCounts.get(dn)-1); String peerName = peerNameForDnAndFn.get(dn+'/'+fn);; modifyPeerNameCount(dn, peerName, -1); advCache.remove(dn, fn); } private void modifyPeerNameCount(String dn, String peerName, int delta) { int oldCount = expectedPeersInDirectory.get(dn).get(peerName); expectedPeersInDirectory.get(dn).put(peerName, oldCount + delta); } private int getExpectedPeerCount(String searchDn, String searchPeerName) { return expectedPeersInDirectory.get(searchDn).get(searchPeerName); } private String randomPeerName() { return PEER_NAMES[(int)Math.floor(Math.random() * PEER_NAMES.length)]; } private String randomFile() { return Double.toString(Math.random()); } private String randomFileInDirectory(String dn) { if(expectedFilesInDirectory.get(dn).size() > 0) { return expectedFilesInDirectory.get(dn).iterator().next(); } return null; } private String randomDirectory() { return DIRECTORIES[(int)Math.floor(Math.random() * DIRECTORIES.length)]; } private <T> T randomSelection(List<T> options) { int selection = (int)Math.floor(Math.random() * options.size()); return options.remove(selection); } private void complete(boolean success) { this.successful = success; completionLatch.countDown(); } public boolean isSuccessful() { return successful; } protected PeerAdvertisement createPeerAdvert(PeerGroupID pgID, String peerName) { PeerAdvertisement peerAdv = (PeerAdvertisement) AdvertisementFactory.newAdvertisement(PeerAdvertisement.getAdvertisementType()); peerAdv.setPeerGroupID(pgID); peerAdv.setPeerID(IDFactory.newPeerID(pgID)); peerAdv.setName(peerName); return peerAdv; } }