package com.limegroup.gnutella; import java.io.File; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.limegroup.gnutella.settings.SharingSettings; import com.limegroup.gnutella.util.Comparators; import com.limegroup.gnutella.util.ProcessingQueue; /** * Singleton that manages saved files. * * Every three minutes it erases the stored data and adds new information, * as read from the disk. */ public final class SavedFileManager implements Runnable { private static final Log LOG = LogFactory.getLog(SavedFileManager.class); private static SavedFileManager INSTANCE = new SavedFileManager(); public static SavedFileManager instance() { return INSTANCE; } private SavedFileManager() { // Run the task every three minutes, starting in 10 seconds. RouterService.schedule(this, 10 * 1000, 3 * 60 * 1000); } /** * The queue that the task runs in. */ private static final ProcessingQueue QUEUE = new ProcessingQueue("SavedFileLoader"); /** * A Set of URNs in the saved folder. * * LOCKING: Obtain this */ private Set /* of URN */ _urns = new HashSet(); /** * A set of the filenames of the saved files. * * LOCKING: Obtain this */ private Set /* of String */ _names = new TreeSet(Comparators.caseInsensitiveStringComparator()); /** * Adds a new Saved File with the given URNs. */ public synchronized void addSavedFile(File f, Set urns) { if(LOG.isDebugEnabled()) LOG.debug("Adding: " + f + " with: " + urns); _names.add(f.getName()); for(Iterator i = urns.iterator(); i.hasNext();) _urns.add(i.next()); } /** * Determines if the given URN or name is saved. */ public synchronized boolean isSaved(URN urn, String name) { return (urn != null && _urns.contains(urn)) || _names.contains(name); } /** * Attempts to load the saved files. */ public void run() { QUEUE.add(new Runnable() { public void run() { load(); } }); } /** * Loads up any names & urns */ private void load() { LOG.trace("Loading Saved Files"); Set urns = new HashSet(); Set names = new TreeSet(Comparators.caseInsensitiveStringComparator()); UrnCallback callback = new UrnCallback() { public void urnsCalculated(File f, Set urns) { synchronized(SavedFileManager.this) { _urns.addAll(urns); } } public boolean isOwner(Object o) { return o == SavedFileManager.this; } }; Set saveDirs = SharingSettings.getAllSaveDirectories(); for(Iterator i = saveDirs.iterator(); i.hasNext(); ) loadDirectory((File)i.next(), urns, names, callback); synchronized(this) { _urns.addAll(urns); _names.addAll(names); } } /** * Loads a single saved directory. */ private void loadDirectory(File directory, Set tempUrns, Set tempNames, UrnCallback callback) { File[] savedFiles = directory.listFiles(); if(savedFiles == null) return; for(int i = 0; i < savedFiles.length; i++) { File file = savedFiles[i]; if(!file.isFile() || !file.exists()) continue; if(LOG.isTraceEnabled()) LOG.trace("Loading: " + file); tempNames.add(file.getName()); Set urns = UrnCache.instance().getUrns(file); if(urns.isEmpty()) // if not calculated, calculate at some point. UrnCache.instance().calculateAndCacheUrns(file, callback); else // otherwise, add without waiting. tempUrns.addAll(urns); } } }