You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by br...@apache.org on 2013/05/01 19:08:00 UTC

svn commit: r1478099 - /ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java

Author: bramk
Date: Wed May  1 17:08:00 2013
New Revision: 1478099

URL: http://svn.apache.org/r1478099
Log:
ACE-346 Switched dir check from lastmodified to checksum

Last-modified is not good enough as some filesystems (eg ext3) round it to a seconds..


Modified:
    ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java

Modified: ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java?rev=1478099&r1=1478098&r2=1478099&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java (original)
+++ ace/trunk/org.apache.ace.obr/src/org/apache/ace/obr/storage/file/BundleFileStore.java Wed May  1 17:08:00 2013
@@ -25,7 +25,10 @@ import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.math.BigInteger;
 import java.nio.channels.FileChannel;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.Dictionary;
 import java.util.Stack;
 import java.util.jar.Attributes;
@@ -58,7 +61,7 @@ public class BundleFileStore implements 
     private volatile MetadataGenerator m_metadata;
     private volatile LogService m_log;
 
-    private volatile long m_dirLastModified;
+    private volatile String m_dirChecksum;
     private volatile File m_dir;
 
     /**
@@ -69,10 +72,9 @@ public class BundleFileStore implements 
     public void synchronizeMetadata() throws IOException {
         File dir = m_dir;
         synchronized (REPOSITORY_XML) {
-            long dirLastmodified = getDirLastModified(dir);
-            if (dirLastmodified > m_dirLastModified) {
+            if (m_dirChecksum == null || !m_dirChecksum.equals(getDirChecksum(dir))) {
                 m_metadata.generateMetadata(dir);
-                m_dirLastModified = getDirLastModified(dir);
+                m_dirChecksum = getDirChecksum(dir);
             }
         }
     }
@@ -155,13 +157,9 @@ public class BundleFileStore implements 
                 }
 
                 m_dir = newDir;
-                m_dirLastModified = 0l;
+                m_dirChecksum = "";
             }
         }
-        else {
-            // clean up after getting a null as dictionary, as the service is going to be pulled afterwards
-            m_dirLastModified = 0l;
-        }
     }
 
     /**
@@ -176,35 +174,46 @@ public class BundleFileStore implements 
         }
     }
 
+
     /**
-     * Returns the highest last-modified for the directory by recursively looking at all directories and files.
+     * Computes a magic checksum used to determine whether there where changes in the directory without actually looking
+     * into the files or using observation.
      * 
      * @param dir
      *            The directory
-     * @return the Last-modified
+     * @return The checksum
      */
-    private long getDirLastModified(File dir) {
-        long highest = 0l;
+    private String getDirChecksum(File dir) {
+        long start = System.nanoTime();
+
+        MessageDigest digest = null;
+        try {
+            digest = MessageDigest.getInstance("MD5");
+        }
+        catch (NoSuchAlgorithmException e) {
+            // really should not happen
+            m_log.log(LogService.LOG_WARNING, "Unable to get an MD5 digest. Metadata will refresh every ten minutes.", e);
+            return "" + (System.currentTimeMillis() / 600000);
+        }
+
         Stack<File> dirs = new Stack<File>();
         dirs.push(dir);
         while (!dirs.isEmpty()) {
             File pwd = dirs.pop();
-            long modified = pwd.lastModified();
-            if (modified > highest) {
-                highest = modified;
-            }
             for (File file : pwd.listFiles()) {
                 if (file.isDirectory()) {
                     dirs.push(file);
                     continue;
                 }
-                modified = file.lastModified();
-                if (modified > highest) {
-                    highest = modified;
-                }
+                // basically we hash the filenames, but...
+                // include last-modified to detect touched files
+                // include length to work around last-modified rounding issues
+                String magic = file.getName() + file.length() + file.lastModified();
+                digest.update(magic.getBytes());
             }
         }
-        return highest;
+        String checksum = new BigInteger(digest.digest()).toString();
+        return checksum;
     }
 
     /**