Author: dbkr
Date: 2006-05-05 19:55:39 +0000 (Fri, 05 May 2006)
New Revision: 8611

Added:
   trunk/apps/fnmail/src/fnmail/MailLog.java
   trunk/apps/fnmail/src/fnmail/utils/DateStringFactory.java
Modified:
   trunk/apps/fnmail/src/fnmail/Contact.java
   trunk/apps/fnmail/src/fnmail/MailFetcher.java
   trunk/apps/fnmail/src/fnmail/MessageSender.java
   trunk/apps/fnmail/src/fnmail/fcp/FCPConnection.java
   trunk/apps/fnmail/src/fnmail/fcp/HighLevelFCPClient.java
   trunk/apps/fnmail/src/fnmail/fcp/NoNodeConnectionException.java
Log:
Backwards incompatible change - use dates in the keys. Also fixes a bug that 
stopped it from working if the node was shut down and started up again.


Modified: trunk/apps/fnmail/src/fnmail/Contact.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/Contact.java   2006-05-05 18:38:50 UTC (rev 
8610)
+++ trunk/apps/fnmail/src/fnmail/Contact.java   2006-05-05 19:55:39 UTC (rev 
8611)
@@ -1,55 +1,22 @@
 package fnmail;

 import java.io.File;
+import java.io.IOException;
 import java.io.FileReader;
-import java.io.FileOutputStream;
 import java.io.BufferedReader;
-import java.io.PrintWriter;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
+import java.util.Date;

+import fnmail.utils.DateStringFactory;
+
 public class Contact {
        public static final String KEYFILE = "key";
-       private static final String LOGFILE = "log";
-
+       private static final String LOGFILE_PREFIX = "log-";
+       private final File contact_dir;
        private final File keyfile;
-       private final File logfile;
-       private HashMap messages;
-       private int lastMessageId;

        Contact(File dir) {
+               this.contact_dir = dir;
                this.keyfile = new File(dir, KEYFILE);
-               this.logfile = new File(dir, LOGFILE);
-               
-               this.lastMessageId = 0;
-               
-               this.messages = new HashMap();
-               
-               FileReader frdr;
-               try {
-                       frdr = new FileReader(this.logfile);
-               
-               
-                       BufferedReader br = new BufferedReader(frdr);
-                       String line;
-                       
-                       while ( (line = br.readLine()) != null) {
-                               String[] parts = line.split("=");
-                               
-                               if (parts.length != 2) continue;
-                               
-                               int thisnum = Integer.parseInt(parts[0]);
-                               if (thisnum > this.lastMessageId)
-                                       this.lastMessageId = thisnum;
-                               this.messages.put(new Integer(thisnum), 
parts[1]);
-                       }
-                       
-                       frdr.close();
-               } catch (IOException ioe) {
-                       return;
-               }
        }

        public String getKey() throws IOException {
@@ -60,42 +27,24 @@
                return key;
        }

-       public int getNextMessageId() {
-               return this.lastMessageId + 1;
+       public MailLog getLog(String date) {
+               return new MailLog(new File(this.contact_dir, LOGFILE_PREFIX + 
date));
        }

-       public void addMessage(int num, String checksum) {
-               this.messages.put(new Integer(num), checksum);
-               if (num > this.lastMessageId)
-                       this.lastMessageId = num;
-               this.writeLogFile();
-       }
-       
-       private void writeLogFile() {
-               FileOutputStream fos;
-               try {
-                       fos = new FileOutputStream(this.logfile);
-               } catch (IOException ioe) {
-                       return;
-               }
+       public void pruneLogs(Date keepafter) {
+               File[] files = contact_dir.listFiles();

-               PrintWriter pw = new PrintWriter(fos);
-               
-               Iterator i = this.messages.entrySet().iterator();
-               while (i.hasNext()) {
-                       Map.Entry e = (Map.Entry)i.next();
-                       
-                       Integer num = (Integer)e.getKey();
-                       String checksum = (String)e.getValue();
-                       pw.println(num.toString()+"="+checksum);
+               int i;
+               for (i = 0; i< files.length; i++) {
+                       if (!files[i].getName().startsWith(LOGFILE_PREFIX))
+                               continue;
+                       Date logdate = 
DateStringFactory.DateFromKeyString(files[i].getName().substring(LOGFILE_PREFIX.length()));
+                       if (logdate == null) {
+                               // couldn't parse the date... hmm
+                               files[i].delete();
+                       } else if (logdate.before(keepafter)) {
+                               files[i].delete();
+                       }
                }
-               
-               pw.flush();
-               
-               try {
-                       fos.close();
-               } catch (IOException ioe) {
-                       return;
-               }
        }
 }

Modified: trunk/apps/fnmail/src/fnmail/MailFetcher.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/MailFetcher.java       2006-05-05 18:38:50 UTC 
(rev 8610)
+++ trunk/apps/fnmail/src/fnmail/MailFetcher.java       2006-05-05 19:55:39 UTC 
(rev 8611)
@@ -2,6 +2,7 @@

 import fnmail.fcp.FCPConnection;
 import fnmail.fcp.HighLevelFCPClient;
+import fnmail.utils.DateStringFactory;

 import java.io.File;
 import java.io.IOException;
@@ -10,6 +11,8 @@
 import java.io.FileReader;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Calendar;
+import java.util.TimeZone;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;

@@ -18,6 +21,9 @@
        private File contact_dir;
        private final FCPConnection fcpconn;
        private final SimpleDateFormat sdf;
+       private static final int POLL_AHEAD = 3;
+       private static int PASSES_PER_DAY = 3;
+       private static int MAX_DAYS_BACK = 30;

        MailFetcher(MessageBank m, File ctdir, FCPConnection fcpc) {
                this.mb = m;
@@ -36,21 +42,42 @@
        }

        private void fetch_from(Contact contact) {
+               int i;
+               for (i = 1 - MAX_DAYS_BACK; i <= 0; i++) {
+                       String datestr = 
DateStringFactory.getOffsetKeyString(i);
+                       MailLog log = contact.getLog(datestr);
+                       
+                       if (log.getPasses() < PASSES_PER_DAY) {
+                               this.fetch_day(contact, log, datestr);
+                               // don't count passes for today since more
+                               // mail may arrive
+                               if (i < 0) log.incPasses();
+                       }
+               }
+               
+               TimeZone gmt = TimeZone.getTimeZone("GMT");
+               Calendar cal = Calendar.getInstance(gmt);
+               cal.setTime(new Date());
+               
+               cal.add(Calendar.DAY_OF_MONTH, 0 - MAX_DAYS_BACK);
+               contact.pruneLogs(cal.getTime());
+       }
+       
+       public void fetch_day(Contact contact, MailLog log, String date) {
                HighLevelFCPClient fcpcli;
                fcpcli = new HighLevelFCPClient(this.fcpconn);

-               
                String keybase;
                try {
-                       keybase = contact.getKey();
+                       keybase = contact.getKey() + date + "-";
                } catch (IOException ioe) {
                        // Jinkies, Scoob! No key!
                        return;
                }

-               int startnum = contact.getNextMessageId();
+               int startnum = log.getNextMessageId();

-               for (int i = startnum; i < startnum + 3; i++) {
+               for (int i = startnum; i < startnum + POLL_AHEAD; i++) {
                        System.out.println("trying to fetch "+keybase+i);


@@ -59,7 +86,7 @@
                        if (result != null) {
                                try {
                                        String checksum = 
this.storeMessage(result);
-                                       contact.addMessage(i, checksum);
+                                       log.addMessage(i, checksum);
                                } catch (IOException ioe) {
                                        continue;
                                }

Added: trunk/apps/fnmail/src/fnmail/MailLog.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/MailLog.java   2006-05-05 18:38:50 UTC (rev 
8610)
+++ trunk/apps/fnmail/src/fnmail/MailLog.java   2006-05-05 19:55:39 UTC (rev 
8611)
@@ -0,0 +1,108 @@
+package fnmail;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileOutputStream;
+import java.io.BufferedReader;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+
+
+class MailLog {
+       private final File logfile;
+       private HashMap messages;
+       private int lastMessageId;
+       private int passes;
+       
+       MailLog(File logfile) {
+               this.lastMessageId = 0;
+               this.passes = 0;
+               
+               this.messages = new HashMap();
+               this.logfile = logfile;
+               
+               FileReader frdr;
+               try {
+                       frdr = new FileReader(this.logfile);
+               
+               
+                       BufferedReader br = new BufferedReader(frdr);
+                       String line;
+                       
+                       while ( (line = br.readLine()) != null) {
+                               String[] parts = line.split("=");
+                               
+                               if (parts.length != 2) continue;
+                               
+                               System.out.println(parts[0]);
+                               if (parts[0].equalsIgnoreCase("passes")) {
+                                       this.passes = 
Integer.parseInt(parts[1]);
+                                       continue;
+                               }
+                               
+                               int thisnum = Integer.parseInt(parts[0]);
+                               if (thisnum > this.lastMessageId)
+                                       this.lastMessageId = thisnum;
+                               this.messages.put(new Integer(thisnum), 
parts[1]);
+                       }
+                       
+                       frdr.close();
+               } catch (IOException ioe) {
+                       return;
+               }
+       }
+       
+       public int incPasses() {
+               this.passes++;
+               this.writeLogFile();
+               return this.passes;
+       }
+       
+       public int getPasses() {
+               return this.passes;
+       }
+
+       public int getNextMessageId() {
+               return this.lastMessageId + 1;
+       }
+       
+       public void addMessage(int num, String checksum) {
+               this.messages.put(new Integer(num), checksum);
+               if (num > this.lastMessageId)
+                       this.lastMessageId = num;
+               this.writeLogFile();
+       }
+       
+       private void writeLogFile() {
+               FileOutputStream fos;
+               try {
+                       fos = new FileOutputStream(this.logfile);
+               } catch (IOException ioe) {
+                       return;
+               }
+               
+               PrintWriter pw = new PrintWriter(fos);
+               
+               pw.println("passes="+this.passes);
+               
+               Iterator i = this.messages.entrySet().iterator();
+               while (i.hasNext()) {
+                       Map.Entry e = (Map.Entry)i.next();
+                       
+                       Integer num = (Integer)e.getKey();
+                       String checksum = (String)e.getValue();
+                       pw.println(num.toString()+"="+checksum);
+               }
+               
+               pw.flush();
+               
+               try {
+                       fos.close();
+               } catch (IOException ioe) {
+                       return;
+               }
+       }
+}

Modified: trunk/apps/fnmail/src/fnmail/MessageSender.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/MessageSender.java     2006-05-05 18:38:50 UTC 
(rev 8610)
+++ trunk/apps/fnmail/src/fnmail/MessageSender.java     2006-05-05 19:55:39 UTC 
(rev 8611)
@@ -13,6 +13,7 @@
 import fnmail.fcp.FCPInsertErrorMessage;
 import fnmail.fcp.FCPBadFileException;
 import fnmail.utils.EmailAddress;
+import fnmail.utils.DateStringFactory;

 public class MessageSender implements Runnable {
        public static final String OUTBOX_DIR = "outbox";
@@ -119,7 +120,7 @@
                }

                if (addr.domain.equalsIgnoreCase("nim.fnmail")) {
-                       if (this.slotinsert(msg, NIM_KEY_PREFIX+addr.user)) {
+                       if (this.slotinsert(msg, 
NIM_KEY_PREFIX+addr.user+"-"+DateStringFactory.getKeyString())) {
                                msg.delete();
                        }
                }

Modified: trunk/apps/fnmail/src/fnmail/fcp/FCPConnection.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/fcp/FCPConnection.java 2006-05-05 18:38:50 UTC 
(rev 8610)
+++ trunk/apps/fnmail/src/fnmail/fcp/FCPConnection.java 2006-05-05 19:55:39 UTC 
(rev 8611)
@@ -18,13 +18,19 @@
        public FCPConnection(FCPContext ctx) {
                this.fcpctx = ctx;
                this.clients = new HashMap();
-               this.nextMsgId = 1;

+               this.tryConnect();
+       }
+       
+       private void tryConnect() {
+               if (this.conn != null) return;
+               
                try {
+                       this.nextMsgId = 1;
                        this.conn = this.fcpctx.getConn();
                        this.is = this.conn.getInputStream();
                        this.os = this.conn.getOutputStream();
-               
+                       
                        FCPMessage hello = new FCPMessage(this.nextMsgId, 
"ClientHello");
                        this.nextMsgId++;
                        hello.writeto(this.os);
@@ -38,14 +44,10 @@
                                System.out.println("Warning - got 
'"+reply.getType()+"' from node, expecting 'NodeHello'");
                        }
                } catch (IOException ioe) {
-                       System.out.println("Warning - could not connect to node 
- "+ioe.getMessage());
-                       try {
-                               if (this.conn != null) {
-                                       this.conn.close();
-                               }
-                       } catch (IOException ioe2) {
-                       }
                        this.conn = null;
+                       this.is = null;
+                       this.os = null;
+                       return;
                } catch (FCPBadFileException bfe) {
                        // won't be thrown from a hello, so should really
                        // never get here!
@@ -55,18 +57,16 @@
        public void run() {
                while (true) {
                        try {
-                               if (this.conn == null) {
-                                       this.conn = this.fcpctx.getConn();
-                                       this.is = this.conn.getInputStream();
-                                       this.os = this.conn.getOutputStream();
-                               }
+                               this.tryConnect();
+                               if (this.conn == null) throw new IOException();

                                FCPMessage msg = this.getMessage();
                                if (msg.getType() == null) throw new 
IOException("Connection closed");
                                this.dispatch(msg);
                        } catch (IOException ioe) {
-                               System.out.println("Warning - error 
communicating with node - "+ioe.getMessage());
                                this.conn = null;
+                               this.os = null;
+                               this.is = null;
                                // tell all our clients it's all over
                                Iterator i = this.clients.values().iterator();
                                while (i.hasNext()) {
@@ -92,12 +92,12 @@
        }

        public synchronized void doRequest(FCPClient cli, FCPMessage msg) 
throws NoNodeConnectionException, FCPBadFileException {
-               if (this.os == null) throw new NoNodeConnectionException();
+               if (this.os == null) throw new NoNodeConnectionException("No 
Connection");
                this.clients.put(msg.getId(), cli);
                try {
                        msg.writeto(this.os);
                } catch (IOException ioe) {
-                       throw new NoNodeConnectionException();
+                       throw new NoNodeConnectionException(ioe.getMessage());
                }
        }


Modified: trunk/apps/fnmail/src/fnmail/fcp/HighLevelFCPClient.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/fcp/HighLevelFCPClient.java    2006-05-05 
18:38:50 UTC (rev 8610)
+++ trunk/apps/fnmail/src/fnmail/fcp/HighLevelFCPClient.java    2006-05-05 
19:55:39 UTC (rev 8611)
@@ -25,6 +25,7 @@
                                break;
                        } catch (NoNodeConnectionException nnce) {
                                try {
+                                       System.out.println("got no conn 
exception: "+nnce.getMessage());
                                        Thread.sleep(5000);
                                } catch (InterruptedException ie) {
                                }

Modified: trunk/apps/fnmail/src/fnmail/fcp/NoNodeConnectionException.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/fcp/NoNodeConnectionException.java     
2006-05-05 18:38:50 UTC (rev 8610)
+++ trunk/apps/fnmail/src/fnmail/fcp/NoNodeConnectionException.java     
2006-05-05 19:55:39 UTC (rev 8611)
@@ -1,5 +1,11 @@
 package fnmail.fcp;

 public class NoNodeConnectionException extends Exception {
+       NoNodeConnectionException() {
+               super();
+       }

+       NoNodeConnectionException(String s) {
+               super(s);
+       }
 }

Added: trunk/apps/fnmail/src/fnmail/utils/DateStringFactory.java
===================================================================
--- trunk/apps/fnmail/src/fnmail/utils/DateStringFactory.java   2006-05-05 
18:38:50 UTC (rev 8610)
+++ trunk/apps/fnmail/src/fnmail/utils/DateStringFactory.java   2006-05-05 
19:55:39 UTC (rev 8611)
@@ -0,0 +1,34 @@
+package fnmail.utils;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+
+public class DateStringFactory {
+       private static final TimeZone gmt = TimeZone.getTimeZone("GMT");
+       private static final Calendar cal = Calendar.getInstance(gmt);
+       private static final SimpleDateFormat sdf = new 
SimpleDateFormat("yyyyMMdd");
+
+       public static String getKeyString() {
+               return getOffsetKeyString(0);
+       }
+       
+       // get a date in a format we use for keys, offset from today
+       public static synchronized String getOffsetKeyString(int offset) {
+               cal.setTime(new Date());
+               cal.add(Calendar.DAY_OF_MONTH, offset);
+               
+               return sdf.format(cal.getTime());
+       }
+       
+       public static Date DateFromKeyString(String str) {
+               try {
+                       sdf.setLenient(false);
+                       return sdf.parse(str);
+               } catch (ParseException pe) {
+                       return null;
+               }
+       }
+}


Reply via email to