You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by xe...@apache.org on 2012/04/23 07:08:11 UTC
git commit: Add way to force the cassandra-cli to refresh it's schema
patch by Dave Brosius; reviewed by Pavel Yaskevich for CASSANDRA-4052
Updated Branches:
refs/heads/cassandra-1.1 5cd473632 -> 3868cf5f2
Add way to force the cassandra-cli to refresh it's schema
patch by Dave Brosius; reviewed by Pavel Yaskevich for CASSANDRA-4052
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3868cf5f
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3868cf5f
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3868cf5f
Branch: refs/heads/cassandra-1.1
Commit: 3868cf5f2996818ca702e1c409a856e2d285558f
Parents: 5cd4736
Author: Pavel Yaskevich <xe...@apache.org>
Authored: Sun Apr 22 22:04:04 2012 -0700
Committer: Pavel Yaskevich <xe...@apache.org>
Committed: Sun Apr 22 22:04:04 2012 -0700
----------------------------------------------------------------------
CHANGES.txt | 1 +
src/java/org/apache/cassandra/cli/CliClient.java | 211 ++++++++++++++++-
2 files changed, 201 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3868cf5f/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 16b2165..5a491be 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -14,6 +14,7 @@
(CASSANDRA-2261)
* Move CfDef and KsDef validation out of thrift (CASSANDRA-4037)
* Expose repairing by a user provided range (CASSANDRA-3912)
+ * Add way to force the cassandra-cli to refresh it's schema (CASSANDRA-4052)
1.1-dev
http://git-wip-us.apache.org/repos/asf/cassandra/blob/3868cf5f/src/java/org/apache/cassandra/cli/CliClient.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java
index 6c3872b..ded2c2b 100644
--- a/src/java/org/apache/cassandra/cli/CliClient.java
+++ b/src/java/org/apache/cassandra/cli/CliClient.java
@@ -17,6 +17,7 @@
*/
package org.apache.cassandra.cli;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
@@ -49,6 +50,12 @@ import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.UUIDGen;
import org.apache.thrift.TBaseHelper;
import org.apache.thrift.TException;
+import org.codehaus.jackson.JsonEncoding;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonToken;
+import org.codehaus.jackson.type.TypeReference;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.TypeDescription;
@@ -149,12 +156,14 @@ public class CliClient
private Map<String, KsDef> keyspacesMap = new HashMap<String, KsDef>();
private Map<String, AbstractType<?>> cfKeysComparators;
private ConsistencyLevel consistencyLevel = ConsistencyLevel.ONE;
+ private final CfAssumptions assumptions = new CfAssumptions();
private CliUserHelp help;
public CliClient(CliSessionState cliSessionState, Cassandra.Client thriftClient)
{
this.sessionState = cliSessionState;
this.thriftClient = thriftClient;
this.cfKeysComparators = new HashMap<String, AbstractType<?>>();
+ assumptions.readAssumptions();
}
private CliUserHelp getHelp()
@@ -301,6 +310,7 @@ public class CliClient
private void cleanupAndExit()
{
CliMain.disconnect();
+ assumptions.writeAssumptions();
System.exit(0);
}
@@ -309,7 +319,10 @@ public class CliClient
{
// Lazily lookup keyspace meta-data.
if (!(keyspacesMap.containsKey(keyspace)))
+ {
keyspacesMap.put(keyspace, thriftClient.describe_keyspace(keyspace));
+ assumptions.replayAssumptions(keyspace);
+ }
return keyspacesMap.get(keyspace);
}
@@ -1054,7 +1067,8 @@ public class CliClient
String mySchemaVersion = thriftClient.system_update_keyspace(updatedKsDef);
sessionState.out.println(mySchemaVersion);
validateSchemaIsSettled(mySchemaVersion);
- keyspacesMap.put(keyspaceName, thriftClient.describe_keyspace(keyspaceName));
+ keyspacesMap.remove(keyspaceName);
+ getKSMetaData(keySpace);
}
catch (InvalidRequestException e)
{
@@ -1504,16 +1518,27 @@ public class CliClient
return;
String cfName = CliCompiler.getColumnFamily(statement, keyspacesMap.get(keySpace).cf_defs);
- CfDef columnFamily = getCfDef(cfName);
// VALIDATOR | COMPARATOR | KEYS | SUB_COMPARATOR
String assumptionElement = statement.getChild(1).getText().toUpperCase();
- // used to store in this.cfKeysComparator
- AbstractType<?> comparator;
+
// Could be UTF8Type, IntegerType, LexicalUUIDType etc.
String defaultType = CliUtils.unescapeSQLString(statement.getChild(2).getText());
-
+
+ if (applyAssumption(cfName, assumptionElement, defaultType))
+ {
+ assumptions.addAssumption(keySpace, cfName, assumptionElement, defaultType);
+ sessionState.out.println(String.format("Assumption for column family '%s' added successfully.", cfName));
+ }
+ }
+
+ private boolean applyAssumption(String cfName, String assumptionElement, String defaultType)
+ {
+ CfDef columnFamily = getCfDef(cfName);
+ // used to store in this.cfKeysComparator
+ AbstractType<?> comparator;
+
try
{
comparator = TypeParser.parse(defaultType);
@@ -1529,7 +1554,7 @@ public class CliClient
String functions = Function.getFunctionNames();
sessionState.out.println("Type '" + defaultType + "' was not found. Available: " + functions
+ " Or any class which extends o.a.c.db.marshal.AbstractType.");
- return;
+ return false;
}
}
@@ -1556,10 +1581,10 @@ public class CliClient
{
String elements = "VALIDATOR, COMPARATOR, KEYS, SUB_COMPARATOR.";
sessionState.out.println(String.format("'%s' is invalid. Available: %s", assumptionElement, elements));
- return;
+ return false;
}
- sessionState.out.println(String.format("Assumption for column family '%s' added successfully.", columnFamily.getName()));
+ return true;
}
// SHOW API VERSION
@@ -1923,6 +1948,7 @@ public class CliClient
keySpace = keySpaceName;
this.username = username != null ? username : "default";
+ keyspacesMap.remove(keySpace);
CliMain.updateCompletor(CliUtils.getCfNamesByKeySpace(getKSMetaData(keySpace)));
sessionState.out.println("Authenticated to keyspace: " + keySpace);
}
@@ -2100,14 +2126,15 @@ public class CliClient
}
// DESCRIBE KEYSPACE (<keyspace> | <column_family>)?
- private void executeDescribe(Tree statement) throws TException, InvalidRequestException
+ private void executeDescribe(Tree statement) throws TException, InvalidRequestException, NotFoundException
{
if (!CliMain.isConnected())
return;
int argCount = statement.getChildCount();
-
- KsDef currentKeySpace = keyspacesMap.get(keySpace);
+
+ keyspacesMap.remove(keySpace);
+ KsDef currentKeySpace = getKSMetaData(keySpace);
if (argCount > 1) // in case somebody changes Cli grammar
throw new RuntimeException("`describe` command take maximum one argument. See `help describe;`");
@@ -2921,4 +2948,166 @@ public class CliClient
{
sessionState.out.println("Elapsed time: " + (System.currentTimeMillis() - startTime) + " msec(s).");
}
+
+ class CfAssumptions
+ {
+ //Map<KeySpace, Map<ColumnFamily, Map<Property, Value>>>
+ private Map<String, Map<String, Map<String, String>>> assumptions;
+ private boolean assumptionsChanged;
+ private File assumptionDirectory;
+
+ public CfAssumptions()
+ {
+ assumptions = new HashMap<String, Map<String, Map<String, String>>>();
+ assumptionsChanged = false;
+ assumptionDirectory = new File(System.getProperty("user.home"), ".cassandra-cli");
+ assumptionDirectory.mkdirs();
+ }
+
+ public void addAssumption(String keyspace, String columnFamily, String property, String value)
+ {
+ Map<String, Map<String, String>> ksAssumes = assumptions.get(keyspace);
+ if (ksAssumes == null)
+ {
+ ksAssumes = new HashMap<String, Map<String, String>>();
+ assumptions.put(keyspace, ksAssumes);
+ }
+
+ Map<String, String> cfAssumes = ksAssumes.get(columnFamily);
+ if (cfAssumes == null)
+ {
+ cfAssumes = new HashMap<String, String>();
+ ksAssumes.put(columnFamily, cfAssumes);
+ }
+
+ cfAssumes.put(property, value);
+ assumptionsChanged = true;
+ }
+
+ public void replayAssumptions(String keyspace)
+ {
+ if (!CliMain.isConnected() || !hasKeySpace())
+ return;
+
+ Map<String, Map<String, String>> cfAssumes = assumptions.get(keyspace);
+ if (cfAssumes != null)
+ {
+ for (Map.Entry<String, Map<String, String>> cfEntry : cfAssumes.entrySet())
+ {
+ String columnFamily = cfEntry.getKey();
+ Map<String, String> props = cfEntry.getValue();
+
+ for (Map.Entry<String, String> propEntry : props.entrySet())
+ {
+ applyAssumption(columnFamily, propEntry.getKey(), propEntry.getValue());
+ }
+ }
+ }
+ }
+
+ private void readAssumptions()
+ {
+ File assumptionFile = new File(assumptionDirectory, "assumptions.json");
+ if (assumptionFile.isFile())
+ {
+ try
+ {
+ JsonFactory f = new JsonFactory();
+ JsonParser p = f.createJsonParser(assumptionFile);
+ JsonToken token = p.nextToken();
+ while (token != JsonToken.END_OBJECT)
+ {
+ if (token == JsonToken.FIELD_NAME)
+ {
+ String keyspace = p.getText();
+ Map<String, Map<String, String>> ksAssumes = assumptions.get(keyspace);
+ if (ksAssumes == null)
+ {
+ ksAssumes = new HashMap<String, Map<String, String>>();
+ assumptions.put(keyspace, ksAssumes);
+ }
+ token = p.nextToken();
+ while (token != JsonToken.END_ARRAY)
+ {
+ if (token == JsonToken.FIELD_NAME)
+ {
+ String columnFamily = p.getText();
+ Map<String, String> cfAssumes = ksAssumes.get(columnFamily);
+ if (cfAssumes == null)
+ {
+ cfAssumes = new HashMap<String, String>();
+ ksAssumes.put(columnFamily, cfAssumes);
+ }
+
+ token = p.nextToken();
+ while (token != JsonToken.END_ARRAY)
+ {
+ if (token == JsonToken.FIELD_NAME)
+ {
+ String prop = p.getText();
+ p.nextToken();
+ String value = p.getText();
+ cfAssumes.put(prop, value);
+ }
+
+ token = p.nextToken();
+ }
+ }
+ token = p.nextToken();
+ }
+ }
+ token = p.nextToken();
+ }
+ sessionState.out.println("Column Family assumptions read from " + assumptionFile);
+ }
+ catch (Exception e)
+ {
+ sessionState.err.println("Failed reading " + assumptionFile + " file");
+ }
+ }
+ }
+
+ private void writeAssumptions()
+ {
+ if (assumptionsChanged)
+ {
+ File assumptionFile = new File(assumptionDirectory, "assumptions.json");
+ try
+ {
+ JsonFactory f = new JsonFactory();
+ JsonGenerator g = f.createJsonGenerator(assumptionFile, JsonEncoding.UTF8);
+ g.useDefaultPrettyPrinter();
+ g.writeStartObject();
+ for (Map.Entry<String, Map<String, Map<String, String>>> ksEntry : assumptions.entrySet())
+ {
+ g.writeFieldName(ksEntry.getKey());
+ g.writeStartArray();
+ for (Map.Entry<String, Map<String, String>> cfEntry : ksEntry.getValue().entrySet())
+ {
+ g.writeStartObject();
+ g.writeFieldName(cfEntry.getKey());
+ g.writeStartArray();
+ for (Map.Entry<String, String> asEntry : cfEntry.getValue().entrySet())
+ {
+ g.writeStartObject();
+ g.writeStringField(asEntry.getKey(), asEntry.getValue());
+ g.writeEndObject();
+ }
+ g.writeEndArray();
+ g.writeEndObject();
+ }
+ g.writeEndArray();
+ }
+ g.writeEndObject();
+ g.close();
+ sessionState.out.println("Column Family assumptions written to " + assumptionFile);
+ assumptionsChanged = false;
+ }
+ catch (Exception e)
+ {
+ sessionState.err.println("Failed writing " + assumptionFile + " file");
+ }
+ }
+ }
+ }
}