public TrPeerInfo getPeerForAssimilation() { if (peers.isEmpty()) { // We need to use a public peer final ArrayList<File> publicNodeIdFiles = node.getPublicNodeIdFiles(); final File pubPeerFile = publicNodeIdFiles.get(TrUtils.rand.nextInt(publicNodeIdFiles.size())); final TrPeerInfo pnii = Persistence.loadReadOnly(TrPeerInfo.class, pubPeerFile); return pnii; } else { /** * Here we use a trick to pick peers in proportion to the probability that they will be the * fastest peer */ TrPeerInfo bestPeer = null; double bestTimeEstimate = Double.MAX_VALUE; final LinearStat globalSuccessTime = new LinearStat(Integer.MAX_VALUE); globalSuccessTime.sample(1000); globalSuccessTime.sample(2000); for (final TrPeerInfo ifo : peers.values()) { if (ifo.assimilation.successTimeSqrt.total > 0) { globalSuccessTime.sample(ifo.assimilation.successTimeSqrt.mean()); } } for (final Entry<PhysicalNetworkLocation, TrPeerInfo> e : peers.entrySet()) { final double guessFailureProb = e.getValue().assimilation.successRate.getBetaRandom(); double guessSuccessTime; // If we don't have at least 2 samples, use our global success // time if (e.getValue().assimilation.successTimeSqrt.total > 2) { final double guessSuccessTimeSqrt = e.getValue().assimilation.successTimeSqrt.getNormalRandom(); guessSuccessTime = guessSuccessTimeSqrt * guessSuccessTimeSqrt; } else { final double guessSuccessTimeSqrt = globalSuccessTime.getNormalRandom(); guessSuccessTime = guessSuccessTimeSqrt * guessSuccessTimeSqrt; } double timeEstimate = guessSuccessTime + AssimilateSessionImpl.RELAY_ASSIMILATION_TIMEOUT_SECONDS * 1000l * guessFailureProb; if (lastAttemptedRelays.contains(e.getValue())) { timeEstimate *= RECENTLY_ATTEMPTED_PENALTY; } if (timeEstimate < bestTimeEstimate) { bestPeer = e.getValue(); bestTimeEstimate = timeEstimate; } } lastAttemptedRelays.add(bestPeer); while (lastAttemptedRelays.size() > 5) { lastAttemptedRelays.poll(); } return bestPeer; } }
/** * If you need to modify a peer's information you must do it using this method, as it ensures that * persistent peer information gets persisted * * @param addr * @param updateFunction */ public void updatePeerInfo( final PhysicalNetworkLocation addr, final Function<TrPeerInfo, Void> updateFunction) { final File pubNodeFile = node.getFileForPublicNode(addr); if (pubNodeFile.exists()) { Persistence.loadAndModify( TrPeerInfo.class, pubNodeFile, new Persistence.ModifyBlock<TrPeerInfo>() { public void run(final TrPeerInfo object, final Modified modified) { updateFunction.apply(object); } }); } else { updateFunction.apply(peers.get(addr)); } }