Backported CASSANDRA-5818 to cassandra-2.0 patch by Lyuben Todorov; reviewed by Mikhail Stepura
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5d187fb8 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5d187fb8 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5d187fb8 Branch: refs/heads/trunk Commit: 5d187fb82a804f7c9b29c1cf7322436d5488ba4d Parents: a01eb5a Author: Lyuben Todorov <ltodo...@datastax.com> Authored: Thu May 15 20:22:58 2014 -0700 Committer: Mikhail Stepura <mish...@apache.org> Committed: Thu May 15 20:22:58 2014 -0700 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../org/apache/cassandra/db/Directories.java | 72 ++++++++++++++++++++ .../cassandra/service/CassandraDaemon.java | 21 +++++- 3 files changed, 91 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d187fb8/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 30e45c1..ab663eb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -13,6 +13,7 @@ * Fix IllegalStateException in CqlPagingRecordReader (CASSANDRA-7198) * Fix the InvertedIndex trigger example (CASSANDRA-7211) * Add --resolve-ip option to 'nodetool ring' (CASSANDRA-7210) + * Fix duplicated error messages on directory creation error at startup (CASSANDRA-5818) 2.0.8 http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d187fb8/src/java/org/apache/cassandra/db/Directories.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/Directories.java b/src/java/org/apache/cassandra/db/Directories.java index 2db4d9b..e118f86 100644 --- a/src/java/org/apache/cassandra/db/Directories.java +++ b/src/java/org/apache/cassandra/db/Directories.java @@ -80,6 +80,78 @@ public class Directories dataFileLocations[i] = new DataDirectory(new File(locations[i])); } + /** + * Checks whether Cassandra has RWX permissions to the specified directory. + * + * @param dir File object of the directory. + * @param dataDir String representation of the directory's location + * @return status representing Cassandra's RWX permissions to the supplied folder location. + */ + public static boolean hasFullPermissions(File dir, String dataDir) + { + if (!dir.isDirectory()) + { + logger.error("Not a directory {}", dataDir); + return false; + } + else if (!FileAction.hasPrivilege(dir, FileAction.X)) + { + logger.error("Doesn't have execute permissions for {} directory", dataDir); + return false; + } + else if (!FileAction.hasPrivilege(dir, FileAction.R)) + { + logger.error("Doesn't have read permissions for {} directory", dataDir); + return false; + } + else if (dir.exists() && !FileAction.hasPrivilege(dir, FileAction.W)) + { + logger.error("Doesn't have write permissions for {} directory", dataDir); + return false; + } + + return true; + } + + public enum FileAction + { + X, W, XW, R, XR, RW, XRW; + + private FileAction() + { + } + + public static boolean hasPrivilege(File file, FileAction action) + { + boolean privilege = false; + + switch (action) { + case X: + privilege = file.canExecute(); + break; + case W: + privilege = file.canWrite(); + break; + case XW: + privilege = file.canExecute() && file.canWrite(); + break; + case R: + privilege = file.canRead(); + break; + case XR: + privilege = file.canExecute() && file.canRead(); + break; + case RW: + privilege = file.canRead() && file.canWrite(); + break; + case XRW: + privilege = file.canExecute() && file.canRead() && file.canWrite(); + break; + } + return privilege; + } + } + private final String keyspacename; private final String cfname; private final File[] sstableDirectories; http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d187fb8/src/java/org/apache/cassandra/service/CassandraDaemon.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java index 9c7cc94..89d2bb0 100644 --- a/src/java/org/apache/cassandra/service/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java @@ -49,6 +49,7 @@ import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.ColumnFamilyStore; +import org.apache.cassandra.db.Directories; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.MeteredFlusher; import org.apache.cassandra.db.SystemKeyspace; @@ -228,9 +229,23 @@ public class CassandraDaemon { logger.debug("Checking directory {}", dataDir); File dir = new File(dataDir); - if (dir.exists()) - assert dir.isDirectory() && dir.canRead() && dir.canWrite() && dir.canExecute() - : String.format("Directory %s is not accessible.", dataDir); + // check that directories exist. + if (!dir.exists()) + { + logger.error("Directory {} doesn't exist", dataDir); + // if they don't, failing their creation, stop cassandra. + if (!dir.mkdirs()) + { + logger.error("Has no permission to create {} directory", dataDir); + System.exit(3); + } + } + // if directories exist verify their permissions + if (!Directories.hasFullPermissions(dir, dataDir)) + { + // if permissions aren't sufficient, stop cassandra. + System.exit(3); + } } if (CacheService.instance == null) // should never happen