Hi,

An update and another patch. I've found that doing GC before attempting the file move/rename operation allows it to succeed in every permutation I've tried so far. The patch implements this in MaildirMessageMapper.updateFlags(), giving it 5 tries (this may be excessive, I dunno; next time I'll check how many tries it takes).

NB: I switched from FileUtils.moveFile() to File.renameTo() just for the sake of constructing a quick test since it has a boolean return value; I did already try just drop-in replacing it (without the loop), and it also failed.

I *think* this means there's an unreleased File{In,Out}putStream lurking somewhere that needs to be found but, from what I've read, I'm still not sure that I can rule out Windows itself holding the lock even when release() has been explicitly called, which some commentators on the subject seem convinced of.

It's still reporting all messages as Draft, so I shall busy myself investigating that in the meantime.

Regards,
Robin Bankhead

PS - yes, the test classes were also hackishly adjusted for semicolons instead of colons. I don't see much point doing this elegantly unless/until this issue goes somewhere, plus I'm not sure how best to do so :/


# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: C:\srv\apache-james-mailbox-trunk\trunk\maildir # This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java --- src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java Base (BASE) +++ src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java Locally Modified (Based On LOCAL)
@@ -216,7 +216,14 @@
// if the flags don't have change we should not try to move
                     // the file
                     if (newMessageFile.equals(messageFile) == false) {
-                        FileUtils.moveFile(messageFile, newMessageFile);
+                                               byte tries = 0;
+                                               while 
(!messageFile.renameTo(newMessageFile)) {
+                                                       if(++tries >= 5) {
+                                                               throw new 
IOException("Failed renaming '" + messageFile +
+                                                                "' to '" + 
newMessageFile + "' :(");
+                                                       }
+                                                       System.gc();
+                                               }
                         modSeq = newMessageFile.lastModified();

                     } else {
Index: src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
--- src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java Base (BASE) +++ src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java Locally Modified (Based On LOCAL)
@@ -729,7 +729,7 @@
     public static String stripMetaFromName(String fileName) {
         int end = fileName.indexOf(",S="); // the size
         if (end == -1)
-            end = fileName.indexOf(":2,"); // the flags
+ end = fileName.indexOf(MaildirMessageName.FLAG_PREFIX + "2,"); // the flags
         if (end == -1)
             return fileName; // there is no meta data to strip
         return fileName.substring(0, end);
Index: src/main/java/org/apache/james/mailbox/maildir/MaildirMessageName.java
--- src/main/java/org/apache/james/mailbox/maildir/MaildirMessageName.java Base (BASE) +++ src/main/java/org/apache/james/mailbox/maildir/MaildirMessageName.java Locally Modified (Based On LOCAL)
@@ -41,20 +41,25 @@
     public static final String FLAG_SEEN = "S";
     public static final String FLAG_DELETED = "T";

+       // Character used instead of ":" for Windows filesystems.
+       // Using java.io.File.pathSeparator which = ":" on *NIX
+       // and ";" on Windows.
+       public static final String FLAG_PREFIX = File.pathSeparator;
+
     // patterns
public static final String PATTERN_STRING_MESSAGE_NAME = "\\d+\\.\\w+\\..+?";
-    public static final String PATTERN_STRING_FLAGS = ":2,[DFRST]*";
+ public static final String PATTERN_STRING_FLAGS = FLAG_PREFIX + "2,[DFRST]*";
     public static final String PATTERN_STRING_SIZE = ",S=\\d+";
     public static final Pattern PATTERN_MESSAGE =
Pattern.compile(PATTERN_STRING_MESSAGE_NAME + optional(PATTERN_STRING_SIZE) + optional(PATTERN_STRING_FLAGS));

     public static final Pattern PATTERN_UNSEEN_MESSAGES =
- Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + optional(":2,[^S]*")); + Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + optional(FLAG_PREFIX + "2,[^S]*"));

public static final FilenameFilter FILTER_UNSEEN_MESSAGES = createRegexFilter(PATTERN_UNSEEN_MESSAGES);

     public static final Pattern PATTERN_DELETED_MESSAGES =
- Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + ":2,.*" + FLAG_DELETED); + Pattern.compile(PATTERN_STRING_MESSAGE_NAME + PATTERN_STRING_SIZE + FLAG_PREFIX + "2,.*" + FLAG_DELETED);

public static final FilenameFilter FILTER_DELETED_MESSAGES = createRegexFilter(PATTERN_DELETED_MESSAGES);

@@ -250,7 +255,7 @@
* into its components hostname, size and flags and fills the respective variables.
      */
     private void splitHostNameAndMeta() {
-        String[] hostnamemetaFlags = hostnameAndMeta.split(":", 2);
+        String[] hostnamemetaFlags = hostnameAndMeta.split(FLAG_PREFIX, 2);
         if (hostnamemetaFlags.length >= 1) {
           this.hostnameAndMeta = hostnamemetaFlags[0];
           int firstEnd = hostnameAndMeta.indexOf(',');
@@ -272,7 +277,7 @@
         }

         if (hostnamemetaFlags.length >= 2) {
-            this.flagsString = ":" + hostnamemetaFlags[1];
+            this.flagsString = FLAG_PREFIX + hostnamemetaFlags[1];
         }
         if (isMessageNameStrictParse()) {
             if (sizeString == null) {
@@ -364,7 +369,7 @@
      * @return A String valid for Maildir
      */
     public String encodeFlags(Flags flags) {
-        StringBuilder localFlagsString = new StringBuilder(":2,");
+ StringBuilder localFlagsString = new StringBuilder(FLAG_PREFIX + "2,");
         if (flags.contains(Flags.Flag.DRAFT))
             localFlagsString.append(FLAG_DRAFT);
         if (flags.contains(Flags.Flag.FLAGGED))
Index: src/test/java/org/apache/james/mailbox/maildir/MailderMessageNameTest.java --- src/test/java/org/apache/james/mailbox/maildir/MailderMessageNameTest.java Base (BASE) +++ src/test/java/org/apache/james/mailbox/maildir/MailderMessageNameTest.java Locally Modified (Based On LOCAL)
@@ -48,34 +48,34 @@
     public static List<Object[]> testData() {
         List<Object[]> args = new ArrayList<Object[]>();
         // no size, two flags
- Parts parts = Parts.fullName("1328026049.19146_0.km1111:2,RS").timeSeconds(1328026049) + Parts parts = Parts.fullName("1328026049.19146_0.km1111;2,RS").timeSeconds(1328026049) .baseName("1328026049.19146_0.km1111").flagAnswered().flagSeen();
         args.add(valid(parts));

         // size and flag
- parts = Parts.fullName("1328613172.M569643P1862V0000000000000902I00EE42CE_0.km1111,S=13103:2,S") + parts = Parts.fullName("1328613172.M569643P1862V0000000000000902I00EE42CE_0.km1111,S=13103;2,S")
                 .timeSeconds(1328613172).size(13103L)
.baseName("1328613172.M569643P1862V0000000000000902I00EE42CE_0.km1111").flagSeen();
         args.add(valid(parts));

         // size, no flags
- parts = Parts.fullName("1340124194.M723289P3184V0000000000000902I006780E9_6.km1111,S=1344:2,") + parts = Parts.fullName("1340124194.M723289P3184V0000000000000902I006780E9_6.km1111,S=1344;2,") .baseName("1340124194.M723289P3184V0000000000000902I006780E9_6.km1111").timeSeconds(1340124194)
                 .size(1344L);
         args.add(valid(parts));

         // three flags, no size
- parts = Parts.fullName("1106685752.12132_0.km1111:2,FRS").baseName("1106685752.12132_0.km1111") + parts = Parts.fullName("1106685752.12132_0.km1111;2,FRS").baseName("1106685752.12132_0.km1111") .timeSeconds(1106685752).flagFlagged().flagAnswered().flagSeen();
         args.add(valid(parts));

         // with dovecot attributes
- parts = Parts.fullName("1035478339.27041_118.foo.org,S=1000,W=1030:2,S") + parts = Parts.fullName("1035478339.27041_118.foo.org,S=1000,W=1030;2,S") .baseName("1035478339.27041_118.foo.org").timeSeconds(1035478339).size(1000L).flagSeen();
         args.add(valid(parts));

         parts = parts.copy();
-        parts.fullName = "1035478339.27041_118.foo.org,W=1030,S=1000:2,S";
+        parts.fullName = "1035478339.27041_118.foo.org,W=1030,S=1000;2,S";
         args.add(valid(parts));

         // new mail, no info part at all. found in courier maildirs
@@ -84,15 +84,15 @@
         args.add(valid(parts));

         // new mail, generated by james
- parts = Parts.fullName("1356001301.e563087e30181513.foohost,S=629:2,") + parts = Parts.fullName("1356001301.e563087e30181513.foohost,S=629;2,") .baseName("1356001301.e563087e30181513.foohost").timeSeconds(1356001301).size(629L);
         args.add(valid(parts));

- parts = Parts.fullName("1355675588.5c7e107958851103.foohost,S=654:2,S").timeSeconds(1355675588) + parts = Parts.fullName("1355675588.5c7e107958851103.foohost,S=654;2,S").timeSeconds(1355675588) .baseName("1355675588.5c7e107958851103.foohost").size(654L).flagSeen();
         args.add(valid(parts));

- parts = Parts.fullName("1355675651.f3dd564265174501.foohost,S=661:2,") + parts = Parts.fullName("1355675651.f3dd564265174501.foohost,S=661;2,") .baseName("1355675651.f3dd564265174501.foohost").timeSeconds(1355675651).size(661L);
         args.add(valid(parts));



---------------------------------------------------------------------
To unsubscribe, e-mail: server-user-unsubscr...@james.apache.org
For additional commands, e-mail: server-user-h...@james.apache.org

Reply via email to