From ab42d9825016f0c4daa5d92df7f7574027fab6a7 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Wed, 13 Jul 2011 03:18:27 +0000 Subject: [PATCH 1/6] support spaces in path to log4j configuration patch by David Allsopp; reviewed by jbellis for CASSANDRA-2383 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1145849 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + .../cassandra/config/DatabaseDescriptor.java | 2 +- .../service/AbstractCassandraDaemon.java | 26 ++++++++++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9cbff76bd7..828109e8c9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,7 @@ 0.7.8 * fix possibility of spurious UnavailableException for LOCAL_QUORUM reads with dynamic snitch + read repair disabled (CASSANDRA-2870) + * support spaces in path to log4j configuration (CASSANDRA-2383) 0.7.7 diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 837e724204..af63909517 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -100,7 +100,7 @@ public class DatabaseDescriptor try { url = new URL(configUrl); - url.openStream(); // catches well-formed but bogus URLs + url.openStream().close(); // catches well-formed but bogus URLs } catch (Exception e) { diff --git a/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java b/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java index 84f600ae87..24b21e7786 100644 --- a/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/AbstractCassandraDaemon.java @@ -70,12 +70,30 @@ public abstract class AbstractCassandraDaemon implements CassandraDaemon } catch (MalformedURLException ex) { - // load from the classpath. + // then try loading from the classpath. configLocation = AbstractCassandraDaemon.class.getClassLoader().getResource(config); - if (configLocation == null) - throw new RuntimeException("Couldn't figure out log4j configuration."); } - PropertyConfigurator.configureAndWatch(configLocation.getFile(), 10000); + + if (configLocation == null) + throw new RuntimeException("Couldn't figure out log4j configuration: "+config); + + // Now convert URL to a filename + String configFileName = null; + try + { + // first try URL.getFile() which works for opaque URLs (file:foo) and paths without spaces + configFileName = configLocation.getFile(); + File configFile = new File(configFileName); + // then try alternative approach which works for all hierarchical URLs with or without spaces + if (!configFile.exists()) + configFileName = new File(configLocation.toURI()).getCanonicalPath(); + } + catch (Exception e) + { + throw new RuntimeException("Couldn't convert log4j configuration location to a valid file", e); + } + + PropertyConfigurator.configureAndWatch(configFileName, 10000); org.apache.log4j.Logger.getLogger(AbstractCassandraDaemon.class).info("Logging initialized"); } From 69f4fec007989f2ce47a59abf84a98bd02ed8fac Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Thu, 14 Jul 2011 23:42:11 +0000 Subject: [PATCH 2/6] Do not allow extra params to nodetool commands to prevent confusion. Patch by Jon Hermes, reviewed by brandonwilliams for CASSANDRA-2740 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1146923 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/cassandra/tools/NodeCmd.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/java/org/apache/cassandra/tools/NodeCmd.java b/src/java/org/apache/cassandra/tools/NodeCmd.java index 64222e4138..4f128d277c 100644 --- a/src/java/org/apache/cassandra/tools/NodeCmd.java +++ b/src/java/org/apache/cassandra/tools/NodeCmd.java @@ -539,19 +539,19 @@ public class NodeCmd switch (command) { - case RING : nodeCmd.printRing(System.out); break; - case INFO : nodeCmd.printInfo(System.out); break; - case CFSTATS : nodeCmd.printColumnFamilyStats(System.out); break; - case DECOMMISSION : probe.decommission(); break; - case LOADBALANCE : probe.loadBalance(); break; - case CLEARSNAPSHOT : probe.clearSnapshot(); break; - case TPSTATS : nodeCmd.printThreadPoolStats(System.out); break; - case VERSION : nodeCmd.printReleaseVersion(System.out); break; - case COMPACTIONSTATS : nodeCmd.printCompactionStats(System.out); break; - case DISABLEGOSSIP : probe.stopGossiping(); break; - case ENABLEGOSSIP : probe.startGossiping(); break; - case DISABLETHRIFT : probe.stopThriftServer(); break; - case ENABLETHRIFT : probe.startThriftServer(); break; + case RING : complainNonzeroArgs(arguments, command); nodeCmd.printRing(System.out); break; + case INFO : complainNonzeroArgs(arguments, command); nodeCmd.printInfo(System.out); break; + case CFSTATS : complainNonzeroArgs(arguments, command); nodeCmd.printColumnFamilyStats(System.out); break; + case DECOMMISSION : complainNonzeroArgs(arguments, command); probe.decommission(); break; + case LOADBALANCE : complainNonzeroArgs(arguments, command); probe.loadBalance(); break; + case CLEARSNAPSHOT : complainNonzeroArgs(arguments, command); probe.clearSnapshot(); break; + case TPSTATS : complainNonzeroArgs(arguments, command); nodeCmd.printThreadPoolStats(System.out); break; + case VERSION : complainNonzeroArgs(arguments, command); nodeCmd.printReleaseVersion(System.out); break; + case COMPACTIONSTATS : complainNonzeroArgs(arguments, command); nodeCmd.printCompactionStats(System.out); break; + case DISABLEGOSSIP : complainNonzeroArgs(arguments, command); probe.stopGossiping(); break; + case ENABLEGOSSIP : complainNonzeroArgs(arguments, command); probe.startGossiping(); break; + case DISABLETHRIFT : complainNonzeroArgs(arguments, command); probe.stopThriftServer(); break; + case ENABLETHRIFT : complainNonzeroArgs(arguments, command); probe.startThriftServer(); break; case DRAIN : try { probe.drain(); } @@ -647,6 +647,15 @@ public class NodeCmd System.exit(3); } + private static void complainNonzeroArgs(String[] args, NodeCommand cmd) + { + if (args.length > 0) { + System.err.println("Too many arguments for command '"+cmd.toString()+"'."); + printUsage(); + System.exit(1); + } + } + private static void optionalKSandCFs(NodeCommand nc, String[] cmdArgs, NodeProbe probe) throws InterruptedException, IOException { // if there is one additional arg, it's the keyspace; more are columnfamilies From 6ec59e4f27d3ebb5a8962f9579695dde36d32cad Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Fri, 15 Jul 2011 16:07:59 +0000 Subject: [PATCH 3/6] Allow quoted class names in the cli. Patch by Pavel Yaskevich, reviewed by brandonwilliams for CASSANDRA-2899 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1147210 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/cassandra/cli/CliClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java index 0320d65861..bdf6d9267d 100644 --- a/src/java/org/apache/cassandra/cli/CliClient.java +++ b/src/java/org/apache/cassandra/cli/CliClient.java @@ -934,7 +934,7 @@ public class CliClient extends CliUserHelp cfDef.setKey_cache_save_period_in_seconds(Integer.parseInt(mValue)); break; case DEFAULT_VALIDATION_CLASS: - cfDef.setDefault_validation_class(mValue); + cfDef.setDefault_validation_class(CliUtils.unescapeSQLString(mValue)); break; case MIN_COMPACTION_THRESHOLD: cfDef.setMin_compaction_threshold(Integer.parseInt(mValue)); From fcb7e7a7c51778cac7f5e82461b968bfffaefd3c Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Fri, 15 Jul 2011 17:03:13 +0000 Subject: [PATCH 4/6] Expose data_dir through JMX. Patch by Mike Bulman, reviewed by brandonwilliams for CASSANDRA-2770 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1147248 13f79535-47bb-0310-9956-ffa450edef68 --- .../cassandra/service/StorageService.java | 20 +++++++++++++++ .../service/StorageServiceMBean.java | 25 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 2777a48b73..dd86d3ecc6 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -1225,6 +1225,26 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe return stringify(Gossiper.instance.getUnreachableMembers()); } + public String[] getAllDataFileLocations() + { + return DatabaseDescriptor.getAllDataFileLocations(); + } + + public String[] getAllDataFileLocationsForTable(String table) + { + return DatabaseDescriptor.getAllDataFileLocationsForTable(table); + } + + public String getCommitLogLocation() + { + return DatabaseDescriptor.getCommitLogLocation(); + } + + public String getSavedCachesLocation() + { + return DatabaseDescriptor.getSavedCachesLocation(); + } + private List stringify(Iterable endpoints) { List stringEndpoints = new ArrayList(); diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java index 7baac0ceae..91921bad6a 100644 --- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java +++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java @@ -77,6 +77,31 @@ public interface StorageServiceMBean */ public String getReleaseVersion(); + /** + * Get the list of all data file locations from conf + * @return String array of all locations + */ + public String[] getAllDataFileLocations(); + + /** + * Get the list of data file locations for a given keyspace + * @param keyspace the keyspace to get locatiosn for. + * @return String array of all locations + */ + public String[] getAllDataFileLocationsForTable(String table); + + /** + * Get location of the commit log + * @return a string path + */ + public String getCommitLogLocation(); + + /** + * Get location of the saved caches dir + * @return a string path + */ + public String getSavedCachesLocation(); + /** * Retrieve a map of range to end points that describe the ring topology * of a Cassandra cluster. From 65dcec661a1cade3ccd5adb1fa0b47b5df7b972d Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Fri, 15 Jul 2011 17:33:41 +0000 Subject: [PATCH 5/6] Fix column deletion in the cli. Patch by Pavel Yaskevich, reviewed by brandonwilliams for CASSANDRA-2821 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1147258 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/cassandra/cli/CliClient.java | 32 ++++++++++++++++--- .../org/apache/cassandra/cli/CliTest.java | 2 ++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java index bdf6d9267d..799909538f 100644 --- a/src/java/org/apache/cassandra/cli/CliClient.java +++ b/src/java/org/apache/cassandra/cli/CliClient.java @@ -278,20 +278,42 @@ public class CliClient extends CliUserHelp sessionState.out.println("Invalid row, super column, or column specification."); return; } - + + Tree columnTree = (columnSpecCnt >= 1) + ? columnFamilySpec.getChild(2) + : null; + + Tree subColumnTree = (columnSpecCnt == 2) + ? columnFamilySpec.getChild(3) + : null; + if (columnSpecCnt == 1) { // table.cf['key']['column'] + assert columnTree != null; + + byte[] columnNameBytes = (columnTree.getType() == CliParser.FUNCTION_CALL) + ? convertValueByFunction(columnTree, null, null).array() + : columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef); + if (isSuper) - superColumnName = columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef); + superColumnName = columnNameBytes; else - columnName = columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef); + columnName = columnNameBytes; } else if (columnSpecCnt == 2) { + assert columnTree != null; + assert subColumnTree != null; + // table.cf['key']['column']['column'] - superColumnName = columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef); - columnName = subColumnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 1), cfDef); + superColumnName = (columnTree.getType() == CliParser.FUNCTION_CALL) + ? convertValueByFunction(columnTree, null, null).array() + : columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef); + + columnName = (subColumnTree.getType() == CliParser.FUNCTION_CALL) + ? convertValueByFunction(subColumnTree, null, null).array() + : subColumnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 1), cfDef); } ColumnPath path = new ColumnPath(columnFamily); diff --git a/test/unit/org/apache/cassandra/cli/CliTest.java b/test/unit/org/apache/cassandra/cli/CliTest.java index cbd1a9f455..4795c601e5 100644 --- a/test/unit/org/apache/cassandra/cli/CliTest.java +++ b/test/unit/org/apache/cassandra/cli/CliTest.java @@ -53,6 +53,8 @@ public class CliTest extends CleanupHelper "get CF1 where world2 = long(15);", "get cF1 where world2 = long(15);", "get Cf1 where world2 = long(15);", + "del CF1[utf8('hello')][utf8('world')];", + "del CF1[hello][world2];", "set CF1['hello'][time_spent_uuid] = timeuuid(a8098c1a-f86e-11da-bd1a-00112444be1e);", "create column family CF2 with comparator=IntegerType;", "set CF2['key'][98349387493847748398334] = 'some text';", From 83f9f455d76ec831666f8ed6d6dcbe811145e830 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Sun, 17 Jul 2011 14:13:22 +0000 Subject: [PATCH 6/6] avoid including inferred types in CFupdate patch by pyaskevich; reviewed by jbellis for CASSANDRA-2809 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1147621 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + .../org/apache/cassandra/cli/CliClient.java | 21 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 828109e8c9..df9a855903 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -2,6 +2,7 @@ * fix possibility of spurious UnavailableException for LOCAL_QUORUM reads with dynamic snitch + read repair disabled (CASSANDRA-2870) * support spaces in path to log4j configuration (CASSANDRA-2383) + * avoid including inferred types in CF update (CASSANDRA-2809) 0.7.7 diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java index 799909538f..05177b2145 100644 --- a/src/java/org/apache/cassandra/cli/CliClient.java +++ b/src/java/org/apache/cassandra/cli/CliClient.java @@ -828,11 +828,15 @@ public class CliClient extends CliUserHelp return; String cfName = CliCompiler.getColumnFamily(statement, keyspacesMap.get(keySpace).cf_defs); - // first child is a column family name - CfDef cfDef = getCfDef(cfName); try { + // request correct cfDef from the server + CfDef cfDef = getCfDef(thriftClient.describe_keyspace(this.keySpace), cfName); + + if (cfDef == null) + throw new RuntimeException("Column Family " + cfName + " was not found in the current keyspace."); + String mySchemaVersion = thriftClient.system_update_column_family(updateCfDefAttributes(statement, cfDef)); sessionState.out.println(mySchemaVersion); validateSchemaIsSettled(mySchemaVersion); @@ -1578,7 +1582,18 @@ public class CliClient extends CliUserHelp { return getCfDef(this.keySpace, columnFamilyName); } - + + private CfDef getCfDef(KsDef keyspace, String columnFamilyName) + { + for (CfDef cfDef : keyspace.cf_defs) + { + if (cfDef.name.equals(columnFamilyName)) + return cfDef; + } + + return null; + } + /** * Used to parse meta tree and compile meta attributes into List * @param cfDef - column family definition