From c8f2effca81841716f6095e9d00c47af3fdc5e16 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Mon, 19 Nov 2012 16:04:33 +0000 Subject: [PATCH] * Profiles: Split up files into subdirectories --- .../peermanager/ProfilePersistenceHelper.java | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/router/java/src/net/i2p/router/peermanager/ProfilePersistenceHelper.java b/router/java/src/net/i2p/router/peermanager/ProfilePersistenceHelper.java index a45dccf262..3336a443fa 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfilePersistenceHelper.java +++ b/router/java/src/net/i2p/router/peermanager/ProfilePersistenceHelper.java @@ -8,8 +8,10 @@ import java.io.FilenameFilter; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Date; import java.util.HashSet; +import java.util.List; import java.util.Properties; import java.util.Set; import java.util.zip.GZIPInputStream; @@ -19,6 +21,7 @@ import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.router.RouterContext; +import net.i2p.util.FileUtil; import net.i2p.util.Log; import net.i2p.util.SecureDirectory; import net.i2p.util.SecureFileOutputStream; @@ -41,6 +44,8 @@ class ProfilePersistenceHelper { private static final String SUFFIX = ".txt.gz"; private static final String UNCOMPRESSED_SUFFIX = ".txt"; private static final String OLD_SUFFIX = ".dat"; + private static final String DIR_PREFIX = "p"; + private static final String B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"; /** * If we haven't been able to get a message through to the peer in 3 days, @@ -48,19 +53,22 @@ class ProfilePersistenceHelper { * have changed (etc). * */ - public static final long EXPIRE_AGE = 3*24*60*60*1000; + private static final long EXPIRE_AGE = 3*24*60*60*1000; - private File _profileDir = null; + private final File _profileDir; private Hash _us; public ProfilePersistenceHelper(RouterContext ctx) { _context = ctx; _log = ctx.logManager().getLog(ProfilePersistenceHelper.class); - File profileDir = getProfileDir(); - _us = null; - if (!profileDir.exists()) { - profileDir.mkdirs(); - _log.info("Profile directory " + profileDir.getAbsolutePath() + " created"); + String dir = _context.getProperty(PROP_PEER_PROFILE_DIR, DEFAULT_PEER_PROFILE_DIR); + _profileDir = new SecureDirectory(_context.getRouterDir(), dir); + if (!_profileDir.exists()) + _profileDir.mkdirs(); + for (int j = 0; j < B64.length(); j++) { + File subdir = new SecureDirectory(_profileDir, DIR_PREFIX + B64.charAt(j)); + if (!subdir.exists()) + subdir.mkdir(); } } @@ -169,7 +177,7 @@ class ProfilePersistenceHelper { public Set<PeerProfile> readProfiles() { long start = _context.clock().now(); - Set<File> files = selectFiles(); + List<File> files = selectFiles(); Set<PeerProfile> profiles = new HashSet(files.size()); for (File f : files) { PeerProfile profile = readProfile(f); @@ -182,18 +190,44 @@ class ProfilePersistenceHelper { return profiles; } - private Set<File> selectFiles() { - File files[] = getProfileDir().listFiles(new FilenameFilter() { - public boolean accept(File dir, String filename) { - return (filename.startsWith(PREFIX) && - (filename.endsWith(SUFFIX) || filename.endsWith(OLD_SUFFIX) || filename.endsWith(UNCOMPRESSED_SUFFIX))); - } - }); - Set rv = new HashSet(files.length); - for (int i = 0; i < files.length; i++) - rv.add(files[i]); + private static class ProfileFilter implements FilenameFilter { + public boolean accept(File dir, String filename) { + return (filename.startsWith(PREFIX) && + (filename.endsWith(SUFFIX) || filename.endsWith(OLD_SUFFIX) || filename.endsWith(UNCOMPRESSED_SUFFIX))); + } + } + + private List<File> selectFiles() { + FilenameFilter filter = new ProfileFilter(); + File files[] = _profileDir.listFiles(filter); + if (files != null && files.length > 0) + migrate(files); + List rv = new ArrayList(1024); + for (int j = 0; j < B64.length(); j++) { + File subdir = new File(_profileDir, DIR_PREFIX + B64.charAt(j)); + files = subdir.listFiles(filter); + if (files == null) + continue; + for (int i = 0; i < files.length; i++) + rv.add(files[i]); + } return rv; } + + /** + * Migrate from one-level to two-level directory structure + * @since 0.9.4 + */ + private void migrate(File[] files) { + for (int i = 0; i < files.length; i++) { + File from = files[i]; + if (!from.isFile()) + continue; + File dir = new File(_profileDir, DIR_PREFIX + from.getName().charAt(PREFIX.length())); + File to = new File(dir, from.getName()); + FileUtil.rename(from, to); + } + } private boolean isExpired(long lastSentToSuccessfully) { long timeSince = _context.clock().now() - lastSentToSuccessfully; @@ -342,16 +376,11 @@ class ProfilePersistenceHelper { } private File pickFile(PeerProfile profile) { - return new File(getProfileDir(), PREFIX + profile.getPeer().toBase64() + SUFFIX); + String hash = profile.getPeer().toBase64(); + File dir = new File(_profileDir, DIR_PREFIX + hash.charAt(0)); + return new File(dir, PREFIX + hash + SUFFIX); } - private File getProfileDir() { - if (_profileDir == null) { - String dir = _context.getProperty(PROP_PEER_PROFILE_DIR, DEFAULT_PEER_PROFILE_DIR); - _profileDir = new SecureDirectory(_context.getRouterDir(), dir); - } - return _profileDir; - } /** generate 1000 profiles */ /**** -- GitLab