I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 9b69dad0 authored by zzz's avatar zzz
Browse files

* Addressbook

      - Store last-fetched time so we don't always fetch subscriptions after restart
      - Randomize first fetch time
      - Make most classes package private
parent 729aedee
No related branches found
No related tags found
No related merge requests found
......@@ -38,7 +38,7 @@ import net.i2p.util.EepGet;
* @author Ragnarok
*
*/
public class AddressBook {
class AddressBook {
private String location;
......@@ -88,6 +88,8 @@ public class AddressBook {
* read or cannot be read, return an empty AddressBook.
* Set a maximum size of the remote book to make it a little harder for a malicious book-sender.
*
* Yes, the EepGet fetch() is done in this constructor.
*
* @param subscription
* A Subscription instance pointing at a remote address book.
* @param proxyHost hostname of proxy
......@@ -102,6 +104,7 @@ public class AddressBook {
if (get.fetch()) {
subscription.setEtag(get.getETag());
subscription.setLastModified(get.getLastModified());
subscription.setLastFetched(I2PAppContext.getGlobalContext().clock().now());
}
try {
this.addresses = ConfigParser.parse(tmp);
......
......@@ -47,7 +47,7 @@ import net.i2p.util.SecureFileOutputStream;
*
* @author Ragnarok
*/
public class ConfigParser {
class ConfigParser {
/**
* Strip the comments from a String. Lines that begin with '#' and ';' are
......@@ -143,7 +143,7 @@ public class ConfigParser {
* @param file
* A File to attempt to parse.
* @param map
* A Map to use as the default, if file fails.
* A Map containing values to use as defaults.
* @return A Map containing the key, value pairs from file, or if file
* cannot be read, map.
*/
......@@ -151,6 +151,11 @@ public class ConfigParser {
Map result;
try {
result = ConfigParser.parse(file);
for (Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
String key = (String) iter.next();
if (!result.containsKey(key))
result.put(key, map.get(key));
}
} catch (IOException exp) {
result = map;
try {
......
......@@ -38,7 +38,7 @@ import net.i2p.util.SecureDirectory;
*
*/
public class Daemon {
public static final String VERSION = "2.0.3";
public static final String VERSION = "2.0.4";
private static final Daemon _instance = new Daemon();
private boolean _running;
......@@ -66,6 +66,7 @@ public class Daemon {
router.merge(master, true, null);
Iterator iter = subscriptions.iterator();
while (iter.hasNext()) {
// yes, the EepGet fetch() is done in next()
router.merge((AddressBook) iter.next(), false, log);
}
router.write();
......@@ -97,6 +98,15 @@ public class Daemon {
File etagsFile = new File(home, (String) settings.get("etags"));
File lastModifiedFile = new File(home, (String) settings
.get("last_modified"));
File lastFetchedFile = new File(home, (String) settings
.get("last_fetched"));
long delay;
try {
delay = Long.parseLong((String) settings.get("update_delay"));
} catch (NumberFormatException nfe) {
delay = 12;
}
delay *= 60 * 60 * 1000;
AddressBook master = new AddressBook(masterFile);
AddressBook router = new AddressBook(routerFile);
......@@ -106,7 +116,7 @@ public class Daemon {
defaultSubs.add("http://www.i2p2.i2p/hosts.txt");
SubscriptionList subscriptions = new SubscriptionList(subscriptionFile,
etagsFile, lastModifiedFile, defaultSubs, (String) settings
etagsFile, lastModifiedFile, lastFetchedFile, delay, defaultSubs, (String) settings
.get("proxy_host"), Integer.parseInt((String) settings.get("proxy_port")));
Log log = new Log(logFile);
......@@ -150,6 +160,7 @@ public class Daemon {
defaultSettings.put("subscriptions", "subscriptions.txt");
defaultSettings.put("etags", "etags");
defaultSettings.put("last_modified", "last_modified");
defaultSettings.put("last_fetched", "last_fetched");
defaultSettings.put("update_delay", "12");
if (!homeFile.exists()) {
......@@ -165,7 +176,7 @@ public class Daemon {
Map settings = ConfigParser.parse(settingsFile, defaultSettings);
// wait
try {
Thread.sleep(5*60*1000);
Thread.sleep(5*60*1000 + I2PAppContext.getGlobalContext().random().nextLong(5*60*1000));
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
} catch (InterruptedException ie) {}
......
......@@ -27,7 +27,7 @@ package net.i2p.addressbook;
* @author Ragnarok
*
*/
public class DaemonThread extends Thread {
class DaemonThread extends Thread {
private String[] args;
......
......@@ -33,7 +33,7 @@ import java.util.Date;
* @author Ragnarok
*
*/
public class Log {
class Log {
private File file;
......
......@@ -27,13 +27,14 @@ package net.i2p.addressbook;
* @author Ragnarok
*
*/
public class Subscription {
class Subscription {
private String location;
private String etag;
private String lastModified;
private long lastFetched;
/**
* Construct a Subscription pointing to the address book at location, that
......@@ -47,11 +48,17 @@ public class Subscription {
* @param lastModified
* the last-modified header we recieved the last time we read
* this subscription.
* @param lastFetched when the subscription was last fetched (Java time, as a String)
*/
public Subscription(String location, String etag, String lastModified) {
public Subscription(String location, String etag, String lastModified, String lastFetched) {
this.location = location;
this.etag = etag;
this.lastModified = lastModified;
if (lastFetched != null) {
try {
this.lastFetched = Long.parseLong(lastFetched);
} catch (NumberFormatException nfe) {}
}
}
/**
......@@ -102,4 +109,14 @@ public class Subscription {
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
}
\ No newline at end of file
/** @since 0.8.2 */
public long getLastFetched() {
return this.lastFetched;
}
/** @since 0.8.2 */
public void setLastFetched(long t) {
this.lastFetched = t;
}
}
......@@ -21,31 +21,39 @@
package net.i2p.addressbook;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper; // debug
/**
* An iterator over the subscriptions in a SubscriptionList. Note that this iterator
* returns AddressBook objects, and not Subscription objects.
* Yes, the EepGet fetch() is done in here in next().
*
* @author Ragnarok
*/
public class SubscriptionIterator implements Iterator {
class SubscriptionIterator implements Iterator {
private Iterator subIterator;
private String proxyHost;
private int proxyPort;
private final long delay;
/**
* Construct a SubscriptionIterator using the Subscriprions in List subscriptions.
*
* @param subscriptions
* List of Subscription objects that represent address books.
* @param delay the minimum delay since last fetched for the iterator to actually fetch
* @param proxyHost proxy hostname
* @param proxyPort proxt port number
*/
public SubscriptionIterator(List subscriptions, String proxyHost, int proxyPort) {
public SubscriptionIterator(List subscriptions, long delay, String proxyHost, int proxyPort) {
this.subIterator = subscriptions.iterator();
this.delay = delay;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
......@@ -58,12 +66,24 @@ public class SubscriptionIterator implements Iterator {
return this.subIterator.hasNext();
}
/* (non-Javadoc)
* @see java.util.Iterator#next()
/**
* Yes, the EepGet fetch() is done in here in next().
*
* see java.util.Iterator#next()
* @return an AddressBook (empty if the minimum delay has not been met)
*/
public Object next() {
Subscription sub = (Subscription) this.subIterator.next();
return new AddressBook(sub, this.proxyHost, this.proxyPort);
if (sub.getLastFetched() + this.delay < I2PAppContext.getGlobalContext().clock().now()) {
//System.err.println("Fetching addressbook from " + sub.getLocation());
return new AddressBook(sub, this.proxyHost, this.proxyPort);
} else {
//System.err.println("Addressbook " + sub.getLocation() + " was last fetched " +
// DataHelper.formatDuration(I2PAppContext.getGlobalContext().clock().now() - sub.getLastFetched()) +
// " ago but the minimum delay is " +
// DataHelper.formatDuration(this.delay));
return new AddressBook(Collections.EMPTY_MAP);
}
}
/* (non-Javadoc)
......@@ -72,4 +92,4 @@ public class SubscriptionIterator implements Iterator {
public void remove() {
throw new UnsupportedOperationException();
}
}
\ No newline at end of file
}
......@@ -35,13 +35,15 @@ import java.util.Map;
* @author Ragnarok
*
*/
public class SubscriptionList {
class SubscriptionList {
private List subscriptions;
private File etagsFile;
private File lastModifiedFile;
private File lastFetchedFile;
private final long delay;
private String proxyHost;
......@@ -60,20 +62,24 @@ public class SubscriptionList {
* @param lastModifiedFile
* A file containg the last-modified headers used for conditional
* GET. The file is in the format "url=leastmodified".
* @param delay the minimum delay since last fetched for the iterator to actually fetch
* @param defaultSubs default subscription file
* @param proxyHost proxy hostname
* @param proxyPort proxy port number
*/
public SubscriptionList(File locationsFile, File etagsFile,
File lastModifiedFile, List defaultSubs, String proxyHost,
File lastModifiedFile, File lastFetchedFile, long delay, List defaultSubs, String proxyHost,
int proxyPort) {
this.subscriptions = new LinkedList();
this.etagsFile = etagsFile;
this.lastModifiedFile = lastModifiedFile;
this.lastFetchedFile = lastFetchedFile;
this.delay = delay;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
Map etags;
Map lastModified;
Map lastFetched;
String location;
List locations = ConfigParser.parseSubscriptions(locationsFile,
defaultSubs);
......@@ -87,11 +93,17 @@ public class SubscriptionList {
} catch (IOException exp) {
lastModified = new HashMap();
}
try {
lastFetched = ConfigParser.parse(lastFetchedFile);
} catch (IOException exp) {
lastFetched = new HashMap();
}
Iterator iter = locations.iterator();
while (iter.hasNext()) {
location = (String) iter.next();
this.subscriptions.add(new Subscription(location, (String) etags
.get(location), (String) lastModified.get(location)));
this.subscriptions.add(new Subscription(location, (String) etags.get(location),
(String) lastModified.get(location),
(String) lastFetched.get(location)));
}
}
......@@ -102,18 +114,22 @@ public class SubscriptionList {
* @return A SubscriptionIterator.
*/
public SubscriptionIterator iterator() {
return new SubscriptionIterator(this.subscriptions, this.proxyHost,
return new SubscriptionIterator(this.subscriptions, this.delay, this.proxyHost,
this.proxyPort);
}
/**
* Write the etag and last-modified headers for each Subscription to files.
* Write the etag and last-modified headers,
* and the last-fetched time, for each Subscription to files.
* BUG - If the subscription URL is a cgi containing an '=' the files
* won't be read back correctly; the '=' should be escaped.
*/
public void write() {
Iterator iter = this.subscriptions.iterator();
Subscription sub;
Map etags = new HashMap();
Map lastModified = new HashMap();
Map lastFetched = new HashMap();
while (iter.hasNext()) {
sub = (Subscription) iter.next();
if (sub.getEtag() != null) {
......@@ -122,11 +138,13 @@ public class SubscriptionList {
if (sub.getLastModified() != null) {
lastModified.put(sub.getLocation(), sub.getLastModified());
}
lastFetched.put(sub.getLocation(), "" + sub.getLastFetched());
}
try {
ConfigParser.write(etags, this.etagsFile);
ConfigParser.write(lastModified, this.lastModifiedFile);
ConfigParser.write(lastFetched, this.lastFetchedFile);
} catch (IOException exp) {
}
}
}
\ No newline at end of file
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment