/** * Returns known active commands in an unmodifiable list. The list contains at most {@link * #MAX_COMMANDS_SIZE} elements from the command database. It is safe to call it frequently. * Threads should care of synchronization when iterating over the it. */ public synchronized List getCommands() { List o = commandCollection; if (o == null) { o = Collections.unmodifiableList(new ArrayList(commands.keySet())); commandCollection = o; } return o; }
/** * Returns known contributions in an unmodifiable list. The list contains at most {@link * #MAX_CACHE_SIZE} random elements from the contribution repository. Might return the same list * when called again if there is two little time between the calls. The dynamic type of elements * is ContributionBox. It is safe to call it frequently. Threads should care of synchronization * when iterating over it. */ public synchronized List getContributions() { List o = cacheCollection; if (o == null) { o = Collections.unmodifiableList(new ArrayList(cache.values())); cacheCollection = o; } return o; }
/** * Removes randomly chosen entries until from the cache and commands until the size is not larger * than MAX_CACHE_SIZE and MAX_COMMANDS_SIZE respectively. */ private void cutToSize() { if (MAX_CACHE_SIZE < cache.size()) synchronized (cache) { Vector keyList = new Vector(cache.keySet()); Collections.shuffle(keyList); while (MAX_CACHE_SIZE < cache.size()) { cache.remove(keyList.get(0)); keyList.remove(0); } } if (MAX_COMMANDS_SIZE < commands.size()) synchronized (commands) { Vector keyList = new Vector(commands.keySet()); Collections.shuffle(keyList); while (MAX_COMMANDS_SIZE < commands.size()) { commands.remove(keyList.get(0)); keyList.remove(0); } } }
/** * Initiates an information exchange with a known and living other base if such a base exists. * * @return true if refresh was succesful, false otherwise. */ private boolean refresh() { final String logSender = observer + "#refresh"; final String contrName = ((contributor != null) ? contributor.getName() : null); // --- refreshing local contribution and commands updateLocalInfo(); // --- creating a random permutation of peers Vector peers = null; synchronized (cache) { peers = new Vector(cache.values()); // just to be sure, shouldn't be there anyway if (contrName != null) peers.remove(cache.get(contrName)); } Collections.shuffle(peers); if (peers.isEmpty()) { Logger.debug(logSender, "no peers in cache"); return false; } // --- reset array representations cacheCollection = null; commandCollection = null; // --- trying to talk to random peer IRequest answer = null; Address peer = null; for (int i = 0; i < peers.size(); ++i) { if (!shouldLive) return false; peer = ((ContributionBox) peers.get(i)).contributor; Logger.debug(logSender, "asking " + peer); answer = observer.fireMessage(peer, "collectiveUpdate-" + name, this); while (answer.getStatus() == IRequest.WAITING) { try { Thread.sleep(100); } catch (Exception e) { } } if (answer.getStatus() == IRequest.DONE) break; Logger.debug(logSender, "not accessable: " + peer); } if (answer.getStatus() != IRequest.DONE) { Logger.debug(logSender, "no accessable peers"); observer.collectiveUpdated(null); return false; } else { Collective c = (Collective) answer.getInfo("reply"); // --- remove possible garbage if (contributor != null) { cache.remove(contributor.getName()); c.cache.remove(contributor.getName()); } cache.remove(peer.name); c.cache.remove(peer.name); repairSenderAddress(c, peer); merge(c); observer.collectiveUpdated((ContributionBox) cache.get(c.myContribution.contributor.name)); return true; } }