diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml
index 747874ef42483962aac4a263964f487245a7bf7c..3db3038eaaf328e0cd7d2fb629b74216e2562aa8 100644
--- a/apps/routerconsole/java/build.xml
+++ b/apps/routerconsole/java/build.xml
@@ -89,6 +89,24 @@
         <!-- jar again to get the latest messages_*.class files -->
         <jar destfile="./build/routerconsole.jar" basedir="./build/obj" includes="**/*.class" update="true" />
     </target>
+    <target name="poupdate" depends="compile">
+        <ant target="war" />
+        <!-- Update the messages_*.po files.
+             We need to supply the bat file for windows, and then change the fail property to true -->
+        <exec executable="sh" osfamily="unix" failifexecutionfails="true" >
+            <arg value="./bundle-messages.sh" />
+            <arg value="-p" />
+        </exec>
+        <exec executable="sh" osfamily="mac" failifexecutionfails="true" >
+            <arg value="./bundle-messages.sh" />
+            <arg value="-p" />
+        </exec>
+        <exec executable="cmd" osfamily="windows" failifexecutionfails="true" >
+            <arg value="/c" />
+            <arg value="bundle-messages.bat" />
+            <arg value="-p" />
+        </exec>
+    </target>
     <target name="war" depends="precompilejsp">
         <!-- Don't include the css in the war, the main build.xml will copy it to docs/themes/console/ -->
         <war destfile="build/routerconsole.war" webxml="../jsp/web-out.xml"
diff --git a/apps/routerconsole/java/bundle-messages.sh b/apps/routerconsole/java/bundle-messages.sh
index 7a25d1b047c3d580412732fb6c53e97154b34afe..f757217683083a206baea9bdd4320ae4341e53ef 100755
--- a/apps/routerconsole/java/bundle-messages.sh
+++ b/apps/routerconsole/java/bundle-messages.sh
@@ -2,12 +2,22 @@
 # Update messages_xx.po and messages_xx.class files,
 # from both java and jsp sources.
 # Requires installed programs xgettext, msgfmt, msgmerge, and find.
+#
+# usage:
+#    bundle-messages.sh (generates the resource bundle from the .po file)
+#    bundle-messages.sh -p (updates the .po file from the source tags, then generates the resource bundle)
+#
 # zzz - public domain
 #
 CLASS=net.i2p.router.web.messages
 TMPFILE=build/javafiles.txt
 export TZ=UTC
 
+if [ "$1" = "-p" ]
+then
+	POUPDATE=1
+fi
+
 #
 # generate strings/Countries.java from ../../../installer/resources/countries.txt
 #
@@ -37,8 +47,12 @@ do
 	LG=${i#../locale/messages_}
 	LG=${LG%.po}
 
-	# make list of java files newer than the .po file
-	find $JPATHS -name *.java -newer $i > $TMPFILE
+	if [ "$POUPDATE" = "1" ]
+	then
+		# make list of java files newer than the .po file
+		find $JPATHS -name *.java -newer $i > $TMPFILE
+	fi
+
 	if [ -s build/obj/net/i2p/router/web/messages_$LG.class -a \
 	     build/obj/net/i2p/router/web/messages_$LG.class -nt $i -a \
 	     ! -s $TMPFILE ]
@@ -46,42 +60,46 @@ do
 		continue
 	fi
 
-	echo "Generating ${CLASS}_$LG ResourceBundle..."
-
-	# extract strings from java and jsp files, and update messages.po files
-	# translate calls must be one of the forms:
-	# _("foo")
-	# _x("foo")
-	# intl._("foo")
-	# intl.title("foo")
-	# handler._("foo")
-	# formhandler._("foo")
-	# net.i2p.router.web.Messages.getString("foo")
-	# In a jsp, you must use a helper or handler that has the context set.
-	# To start a new translation, copy the header from an old translation to the new .po file,
-	# then ant distclean updater.
-	find $JPATHS -name *.java > $TMPFILE
-	xgettext -f $TMPFILE -F -L java --from-code=UTF-8 \
-                 --keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
-                 --keyword=handler._ --keyword=formhandler._ \
-                 --keyword=net.i2p.router.web.Messages.getString \
-	         -o ${i}t
-	if [ $? -ne 0 ]
+	if [ "$POUPDATE" = "1" ]
 	then
-		echo 'Warning - xgettext failed, not updating translations'
+	 	echo "Updating the $i file from the tags..."
+		# extract strings from java and jsp files, and update messages.po files
+		# translate calls must be one of the forms:
+		# _("foo")
+		# _x("foo")
+		# intl._("foo")
+		# intl.title("foo")
+		# handler._("foo")
+		# formhandler._("foo")
+		# net.i2p.router.web.Messages.getString("foo")
+		# In a jsp, you must use a helper or handler that has the context set.
+		# To start a new translation, copy the header from an old translation to the new .po file,
+		# then ant distclean updater.
+		find $JPATHS -name *.java > $TMPFILE
+		xgettext -f $TMPFILE -F -L java --from-code=UTF-8 \
+	                 --keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
+	                 --keyword=handler._ --keyword=formhandler._ \
+	                 --keyword=net.i2p.router.web.Messages.getString \
+		         -o ${i}t
+		if [ $? -ne 0 ]
+		then
+			echo 'Warning - xgettext failed, not updating translations'
+			rm -f ${i}t
+			break
+		fi
+		msgmerge -U --backup=none $i ${i}t
+		if [ $? -ne 0 ]
+		then
+			echo 'Warning - msgmerge failed, not updating translations'
+			rm -f ${i}t
+			break
+		fi
 		rm -f ${i}t
-		break
+		# so we don't do this again
+		touch $i
 	fi
-	msgmerge -U --backup=none $i ${i}t
-	if [ $? -ne 0 ]
-	then
-		echo 'Warning - msgmerge failed, not updating translations'
-		rm -f ${i}t
-		break
-	fi
-	rm -f ${i}t
-	# so we don't do this again
-	touch $i
+
+	echo "Generating ${CLASS}_$LG ResourceBundle..."
 
 	# convert to class files in build/obj
 	msgfmt --java -r $CLASS -l $LG -d build/obj $i
diff --git a/build.xml b/build.xml
index 4ea82687db09ab5d63ef91467dee6a803479ecf7..f2e27b1dfb2f1005c8241a49ff0f4d9f0a2fa317 100644
--- a/build.xml
+++ b/build.xml
@@ -32,6 +32,7 @@
         <echo message="  pkgWithDesktopgui: distclean then package everything up with the desktopgui" />
         <echo message="  distWithDesktopgui: pkgWithDesktopgui and javadoc" />
         <echo message="  distcleanWithDesktopgui: clean up all derived files (including desktopgui files)" />
+        <echo message="  poupdate: update the .po files for translators" />
     </target>
     <target name="debianhowto">
         <echo message="To build debian packages, you must run dpkg-buildpackage as root in the source directory. It will then run ant for you. dpkg-buildpackage is found in the 'dpkg-dev' package. Also it should work fine to use the 'fakeroot' package with dpkg-buildpackage, if you don't want to run as root. Please read 'man dpkg-buildpackage' before building any packages yourself." />
@@ -138,6 +139,9 @@
         <copy file="installer/lib/jbigi/jbigi.jar" todir="build" />
         <copy file="apps/addressbook/dist/addressbook.war" todir="build/" />
     </target>
+    <target name="poupdate">
+        <ant dir="apps/routerconsole/java/" target="poupdate" />
+    </target>
     <target name="javadoc">
         <mkdir dir="./build" />
         <mkdir dir="./build/javadoc" />
diff --git a/history.txt b/history.txt
index cfdeb9852294ccebdfacf793fb33332106f4037e..45ede2a7da60674351ddf225ba676b3b3f0c0872 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,13 @@
+2009-11-18 zzz
+    * Build: Don't update the po files by default, add new
+      target "poupdate" to do that.
+    * Netdb:
+      - Floodfill rework part 3 of N: Send closest-to-the-key
+        in DSRM replies
+      - Adjust criteria for following DSRM
+      - Note failed floods in the profile
+      - Reduce max flood
+
 2009-11-16 zzz
     * addressbook: Move class to net.i2p.addressbook
     * build: Take two test scripts out of the installer
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 4c8aefc89f6dd4518753c53ae89c5a95738b6c6a..40028c0e07d435fba561326cfb59f22e74eef24c 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 18;
+    public final static long BUILD = 19;
     /** for example "-test" */
     public final static String EXTRA = "";
     public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java
index 1664094c29bf01bcb509471c6584935e8a57b52f..4fbaf381e60d38685385c63f69ceb1f82d6ee911 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java
@@ -99,7 +99,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
         }
     }
 
-    private static final int MAX_TO_FLOOD = 9;
+    private static final int MAX_TO_FLOOD = 7;
 
     /**
      *  Send to a subset of all floodfill peers.
@@ -139,6 +139,10 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
             m.setPriority(FLOOD_PRIORITY);
             m.setTarget(target);
             m.setExpiration(_context.clock().now()+FLOOD_TIMEOUT);
+            // note send failure but don't give credit on success
+            // might need to change this
+            Job floodFail = new FloodFailedJob(_context, peer);
+            m.setOnFailedSendJob(floodFail);
             _context.commSystem().processMessage(m);
             flooded++;
             if (_log.shouldLog(Log.INFO))
@@ -149,6 +153,20 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
             _log.info("Flooded the data to " + flooded + " of " + peers.size() + " peers");
     }
 
+    /** note in the profile that the store failed */
+    private static class FloodFailedJob extends JobImpl {
+        private Hash _peer;
+    
+        public FloodFailedJob(RouterContext ctx, Hash peer) {
+            super(ctx);
+            _peer = peer;
+        }
+        public String getName() { return "Flood failed"; }
+        public void runJob() {
+            getContext().profileManager().dbStoreFailed(_peer);
+        }
+    }
+
     private static final int FLOOD_PRIORITY = 200;
     private static final int FLOOD_TIMEOUT = 30*1000;
     
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
index d2bd15d74a5d9e952cf2f6f73f35c495e2e56b59..05a771bd3e83fdad2a35e80f8fe26d62f0bf5891 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java
@@ -299,4 +299,16 @@ class FloodfillPeerSelector extends PeerSelector {
         }
         public int size() { return _matches; }
     }
+    
+    /**
+     * Floodfill peers only. Used only by HandleDatabaseLookupMessageJob to populate the DSRM.
+     *
+     * @param key the original key (NOT the routing key)
+     * @return List of Hash for the peers selected, ordered
+     */
+    @Override
+    public List<Hash> selectNearest(Hash key, int maxNumRouters, Set<Hash> peersToIgnore, KBucketSet kbuckets) {
+        Hash rkey = _context.routingKeyGenerator().getRoutingKey(key);
+        return selectFloodfillParticipants(rkey, maxNumRouters, peersToIgnore, kbuckets);
+    }
 }
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java
index 24c0350f92361ca0d4678dab76024132178cc125..0cd2bb6a046c7d521a66d484c4ddd0a527c0ba17 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java
@@ -1,6 +1,7 @@
 package net.i2p.router.networkdb.kademlia;
 
 import net.i2p.data.Hash;
+import net.i2p.data.RouterInfo;
 import net.i2p.data.i2np.DatabaseSearchReplyMessage;
 import net.i2p.router.JobImpl;
 import net.i2p.router.RouterContext;
@@ -10,7 +11,7 @@ import net.i2p.util.Log;
  * Ask the peer who sent us the DSRM for the RouterInfos.
  *
  * If we have the routerInfo already, try to refetch it from that router itself,
- * if we aren't already connected to that router,
+ * (if the info is old or we don't think it is floodfill)
  * which will help us establish that router as a good floodfill and speed our
  * integration into the network.
  *
@@ -32,9 +33,13 @@ class SingleLookupJob extends JobImpl {
             Hash peer = _dsrm.getReply(i);
             if (peer.equals(getContext().routerHash())) // us
                 continue;
-            if (getContext().netDb().lookupRouterInfoLocally(peer) == null)
+            if (peer.equals(from)) // wtf
+                continue;
+            RouterInfo ri = getContext().netDb().lookupRouterInfoLocally(peer);
+            if (ri == null)
                 getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, from));
-            else if (!getContext().commSystem().isEstablished(peer))
+            else if (ri.getPublished() < getContext().clock().now() - 60*60*1000 ||
+                     !FloodfillNetworkDatabaseFacade.isFloodfill(ri))
                 getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, peer));
         }
     }