/** * This method returns peers that are over sized. The peers that have been seen latest stay. * * @return True if we could remove an oversized peer */ private PeerAddress removeLatestEntryExceedingBagSize() { for (int classMember = Number160.BITS - 1; classMember >= 0; classMember--) { final Map<Number160, PeerAddress> map = peerMap.get(classMember); if (map.size() > bagSize) { long maxValue = Long.MAX_VALUE; PeerAddress removePeerAddress = null; synchronized (map) { for (PeerAddress peerAddress : map.values()) { final long lastSeenOline = peerMapStat.getLastSeenOnlineTime(peerAddress); if (lastSeenOline < maxValue) { maxValue = lastSeenOline; removePeerAddress = peerAddress; } // TODO: idea use a score system rather than // lastSeenOnline, as we might have old reliable peers. if (maxValue == 0) break; } } if (removePeerAddress != null) { return removePeerAddress; } } } return null; }
/** * Remove a peer from the list. In order to not reappear, the node is put for a certain time in a * cache list to keep the node removed. This method is thread-safe. * * @param remotePeer The node that should be removed * @param force A flag that removes a peer immediately. * @return True if the neighbor was removed and added to a cache list. False if peer has not been * removed or is already in the peer removed temporarly list. */ public boolean peerOffline(final PeerAddress remotePeer, final boolean force) { if (logger.isDebugEnabled()) { logger.debug("peer " + remotePeer + " is offline"); } if (remotePeer.getID().isZero() || self().equals(remotePeer.getID())) { return false; } notifyPeerFail(remotePeer, force); Log log; synchronized (peerOfflineLogs) { log = peerOfflineLogs.get(remotePeer); if (log == null) { log = new Log(); peerOfflineLogs.put(remotePeer, log); } } synchronized (log) { if (!force) { if (shouldPeerBeRemoved(log)) { remove(remotePeer, Reason.NOT_REACHABLE); return true; } log.inc(); if (!shouldPeerBeRemoved(log)) { peerMapStat.removeStat(remotePeer); addToMaintenanceQueue(remotePeer); return false; } } else { log.set(maxFail); } } remove(remotePeer, Reason.NOT_REACHABLE); return true; }
private void addToMaintenanceQueue(PeerAddress remotePeer) { if (maintenanceTimeoutsSeconds.length == 0) return; long scheduledCheck; if (peerMapStat.getLastSeenOnlineTime(remotePeer) == 0) { // we need to check now! scheduledCheck = Timings.currentTimeMillis(); } else { // check for next schedule int checked = peerMapStat.getChecked(remotePeer); if (checked >= maintenanceTimeoutsSeconds.length) checked = maintenanceTimeoutsSeconds.length - 1; scheduledCheck = Timings.currentTimeMillis() + (maintenanceTimeoutsSeconds[checked] * 1000L); } synchronized (maintenance) { maintenance.put(remotePeer, scheduledCheck); } }
private void prepareInsertOrUpdate(PeerAddress remotePeer, boolean firstHand) { if (firstHand) { peerMapStat.setSeenOnlineTime(remotePeer); // get the amount of milliseconds for the online time long online = peerMapStat.online(remotePeer); // get the time we want to wait between maintenance checks if (maintenanceTimeoutsSeconds.length > 0) { int checked = peerMapStat.getChecked(remotePeer); if (checked >= maintenanceTimeoutsSeconds.length) checked = maintenanceTimeoutsSeconds.length - 1; long time = maintenanceTimeoutsSeconds[checked] * 1000L; // if we have a higer online time than the maintenance time, // increase checked to increase the maintenace interval. if (online >= time) { peerMapStat.incChecked(remotePeer); } } } addToMaintenanceQueue(remotePeer); }