Fix file system race condition that may cause LogAwareFileLister to fail to 
classify files

patch by Stefania Alborghetti; reviewed by Benjamin Lerer for CASSANDRA-11889


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5cda140b
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5cda140b
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5cda140b

Branch: refs/heads/trunk
Commit: 5cda140bae05c84dde92998df1b85583be69812d
Parents: da07130
Author: Stefania Alborghetti <stefania.alborghe...@datastax.com>
Authored: Tue Aug 2 16:37:15 2016 +0800
Committer: Stefania Alborghetti <stefania.alborghe...@datastax.com>
Committed: Tue Aug 30 08:51:08 2016 +0800

----------------------------------------------------------------------
 CHANGES.txt                                               | 1 +
 src/java/org/apache/cassandra/db/lifecycle/LogFile.java   | 2 +-
 src/java/org/apache/cassandra/db/lifecycle/LogRecord.java | 9 +++++++--
 3 files changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5cda140b/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index cf14f67..7a1fbc5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.9
+ * Fix file system race condition that may cause LogAwareFileLister to fail to 
classify files (CASSANDRA-11889)
  * Fix file handle leaks due to simultaneous compaction/repair and
    listing snapshots, calculating snapshot sizes, or making schema
    changes (CASSANDRA-11594)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5cda140b/src/java/org/apache/cassandra/db/lifecycle/LogFile.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/lifecycle/LogFile.java 
b/src/java/org/apache/cassandra/db/lifecycle/LogFile.java
index 8560410..da5bb39 100644
--- a/src/java/org/apache/cassandra/db/lifecycle/LogFile.java
+++ b/src/java/org/apache/cassandra/db/lifecycle/LogFile.java
@@ -216,7 +216,7 @@ final class LogFile implements AutoCloseable
         // it matches. Because we delete files from oldest to newest, the 
latest update time should
         // always match.
         record.status.onDiskRecord = record.withExistingFiles();
-        if (record.updateTime != record.status.onDiskRecord.updateTime && 
record.status.onDiskRecord.numFiles > 0)
+        if (record.updateTime != record.status.onDiskRecord.updateTime && 
record.status.onDiskRecord.updateTime > 0)
         {
             record.setError(String.format("Unexpected files detected for 
sstable [%s], " +
                                           "record [%s]: last update time [%tT] 
should have been [%tT]",

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5cda140b/src/java/org/apache/cassandra/db/lifecycle/LogRecord.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/lifecycle/LogRecord.java 
b/src/java/org/apache/cassandra/db/lifecycle/LogRecord.java
index d7eb774..c981b02 100644
--- a/src/java/org/apache/cassandra/db/lifecycle/LogRecord.java
+++ b/src/java/org/apache/cassandra/db/lifecycle/LogRecord.java
@@ -26,6 +26,7 @@ import java.nio.file.Paths;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.zip.CRC32;
 
 import org.apache.cassandra.io.sstable.SSTable;
@@ -156,8 +157,12 @@ final class LogRecord
 
     public static LogRecord make(Type type, List<File> files, int minFiles, 
String absolutePath)
     {
-        long lastModified = files.stream().map(File::lastModified).reduce(0L, 
Long::max);
-        return new LogRecord(type, absolutePath, lastModified, 
Math.max(minFiles, files.size()));
+        // CASSANDRA-11889: File.lastModified() returns a positive value only 
if the file exists, therefore
+        // we filter by positive values to only consider the files that still 
exists right now, in case things
+        // changed on disk since getExistingFiles() was called
+        List<Long> positiveModifiedTimes = 
files.stream().map(File::lastModified).filter(lm -> lm > 
0).collect(Collectors.toList());
+        long lastModified = positiveModifiedTimes.stream().reduce(0L, 
Long::max);
+        return new LogRecord(type, absolutePath, lastModified, 
Math.max(minFiles, positiveModifiedTimes.size()));
     }
 
     private LogRecord(Type type, long updateTime)

Reply via email to