public PeerProfile readProfile(File file) { Hash peer = getHash(file.getName()); try { if (peer == null) { _log.error("The file " + file.getName() + " is not a valid hash"); return null; } PeerProfile profile = new PeerProfile(_context, peer); Properties props = new Properties(); loadProps(props, file); long lastSentToSuccessfully = getLong(props, "lastSentToSuccessfully"); if (isExpired(lastSentToSuccessfully)) { if (_log.shouldLog(Log.INFO)) _log.info( "Dropping old profile " + file.getName() + ", since we haven't heard from them in a long time"); file.delete(); return null; } else if (file.getName().endsWith(OLD_SUFFIX)) { // migrate to new file name, ignore failure String newName = file.getAbsolutePath(); newName = newName.substring(0, newName.length() - OLD_SUFFIX.length()) + SUFFIX; boolean success = file.renameTo(new File(newName)); if (!success) // new file exists and on Windows? file.delete(); } profile.setCapacityBonus(getLong(props, "capacityBonus")); profile.setIntegrationBonus(getLong(props, "integrationBonus")); profile.setSpeedBonus(getLong(props, "speedBonus")); profile.setLastHeardAbout(getLong(props, "lastHeardAbout")); profile.setFirstHeardAbout(getLong(props, "firstHeardAbout")); profile.setLastSendSuccessful(getLong(props, "lastSentToSuccessfully")); profile.setLastSendFailed(getLong(props, "lastFailedSend")); profile.setLastHeardFrom(getLong(props, "lastHeardFrom")); profile.setTunnelTestTimeAverage(getDouble(props, "tunnelTestTimeAverage")); profile.setPeakThroughputKBps(getDouble(props, "tunnelPeakThroughput")); profile.setPeakTunnelThroughputKBps(getDouble(props, "tunnelPeakTunnelThroughput")); profile.setPeakTunnel1mThroughputKBps(getDouble(props, "tunnelPeakTunnel1mThroughput")); profile.getTunnelHistory().load(props); // In the interest of keeping the in-memory profiles small, // don't load the DB info at all unless there is something interesting there // (i.e. floodfills) // It seems like we do one or two lookups as a part of handshaking? // Not sure, to be researched. if (getLong(props, "dbHistory.successfulLookups") > 1 || getLong(props, "dbHistory.failedlLokups") > 1) { profile.expandDBProfile(); profile.getDBHistory().load(props); profile.getDbIntroduction().load(props, "dbIntroduction", true); profile.getDbResponseTime().load(props, "dbResponseTime", true); } // profile.getReceiveSize().load(props, "receiveSize", true); // profile.getSendSuccessSize().load(props, "sendSuccessSize", true); profile.getTunnelCreateResponseTime().load(props, "tunnelCreateResponseTime", true); profile.getTunnelTestResponseTime().load(props, "tunnelTestResponseTime", true); if (_log.shouldLog(Log.DEBUG)) _log.debug("Loaded the profile for " + peer.toBase64() + " from " + file.getName()); return profile; } catch (Exception e) { if (_log.shouldLog(Log.WARN)) _log.warn("Error loading properties from " + file.getAbsolutePath(), e); file.delete(); return null; } }