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; } /**