merge from 0.8

git-svn-id: https://svn.apache.org/repos/asf/cassandra/trunk@1155466 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jonathan Ellis 2011-08-09 18:40:54 +00:00
parent 016068ab27
commit 79cf5f6395
10 changed files with 277 additions and 27 deletions

View File

@ -33,6 +33,8 @@
0.8.4
* include files-to-be-streamed in StreamInSession.getSources (CASSANDRA-2972)
* use JAVA env var in cassandra-env.sh (CASSANDRA-2785, 2992)
* avoid doing read for no-op replicate-on-write at CL=1 (CASSANDRA-2892)
0.8.3

2
debian/control vendored
View File

@ -2,7 +2,7 @@ Source: cassandra
Section: misc
Priority: extra
Maintainer: Eric Evans <eevans@apache.org>
Build-Depends: debhelper (>= 5), openjdk-6-jdk (>= 6b11) | java6-sdk, ant (>= 1.7), ant-optional (>= 1.7)
Build-Depends: debhelper (>= 5), openjdk-6-jdk (>= 6b11) | java6-sdk, ant (>= 1.7), ant-optional (>= 1.7), subversion
Homepage: http://cassandra.apache.org
Vcs-Svn: https://svn.apache.org/repos/asf/cassandra/trunk
Vcs-Browser: http://svn.apache.org/viewvc/cassandra/trunk

View File

@ -9,7 +9,6 @@
. /etc/rc.d/init.d/functions
export JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/
export CASSANDRA_HOME=/usr/share/cassandra/
export CASSANDRA_INCLUDE=/usr/share/cassandra/cassandra.in.sh
export CASSANDRA_CONF=/etc/cassandra/conf
@ -19,9 +18,36 @@ log_file=/var/log/cassandra/cassandra.log
pid_file=/var/run/cassandra/cassandra.pid
CASSANDRA_PROG=/usr/sbin/cassandra
# The first existing directory is used for JAVA_HOME if needed.
JVM_SEARCH_DIRS="/usr/lib/jvm/jre /usr/lib/jvm/jre-1.6.* /usr/lib/jvm/java-1.6.*/jre"
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# If JAVA_HOME has not been set, try to determine it.
if [ -z "$JAVA_HOME" ]; then
# If java is in PATH, use a JAVA_HOME that corresponds to that. This is
# both consistent with how the upstream startup script works, and with
# the use of alternatives to set a system JVM (as is done on Debian and
# Red Hat derivatives).
java="`/usr/bin/which java 2>/dev/null`"
if [ -n "$java" ]; then
java=`readlink --canonicalize "$java"`
JAVA_HOME=`dirname "\`dirname \$java\`"`
else
# No JAVA_HOME set and no java found in PATH; search for a JVM.
for jdir in $JVM_SEARCH_DIRS; do
if [ -x "$jdir/bin/java" ]; then
JAVA_HOME="$jdir"
break
fi
done
# if JAVA_HOME is still empty here, punt.
fi
fi
JAVA="$JAVA_HOME/bin/java"
export JAVA_HOME JAVA
case "$1" in
start)
# Cassandra startup

View File

@ -44,6 +44,7 @@ tokens {
NODE_SHOW_CLUSTER_NAME;
NODE_SHOW_VERSION;
NODE_SHOW_KEYSPACES;
NODE_SHOW_SCHEMA;
NODE_THRIFT_GET;
NODE_THRIFT_GET_WITH_CONDITIONS;
NODE_THRIFT_SET;
@ -191,6 +192,8 @@ helpStatement
-> ^(NODE_HELP NODE_SHOW_CLUSTER_NAME)
| HELP SHOW KEYSPACES
-> ^(NODE_HELP NODE_SHOW_KEYSPACES)
| HELP SHOW SCHEMA
-> ^(NODE_HELP NODE_SHOW_SCHEMA)
| HELP SHOW API_VERSION
-> ^(NODE_HELP NODE_SHOW_VERSION)
| HELP CREATE KEYSPACE
@ -284,6 +287,7 @@ showStatement
: showClusterName
| showVersion
| showKeyspaces
| showSchema
;
listStatement
@ -356,6 +360,11 @@ showKeyspaces
-> ^(NODE_SHOW_KEYSPACES)
;
showSchema
: SHOW SCHEMA (keyspace)?
-> ^(NODE_SHOW_SCHEMA (keyspace)?)
;
describeTable
: DESCRIBE KEYSPACE (keyspace)?
-> ^(NODE_DESCRIBE_TABLE (keyspace)?)
@ -573,6 +582,7 @@ TTL: 'TTL';
CONSISTENCYLEVEL: 'CONSISTENCYLEVEL';
INDEX: 'INDEX';
ON: 'ON';
SCHEMA: 'SCHEMA';
IP_ADDRESS
: IntegerPositiveLiteral '.' IntegerPositiveLiteral '.' IntegerPositiveLiteral '.' IntegerPositiveLiteral

View File

@ -26,6 +26,9 @@ import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.*;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import org.apache.commons.lang.StringUtils;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
@ -71,7 +74,7 @@ public class CliClient
COUNTERCOLUMN (CounterColumnType.instance);
private AbstractType validator;
Function(AbstractType validator)
{
this.validator = validator;
@ -139,6 +142,8 @@ public class CliClient
}
private static final String DEFAULT_PLACEMENT_STRATEGY = "org.apache.cassandra.locator.NetworkTopologyStrategy";
private final String NEWLINE = System.getProperty("line.separator");
private final String TAB = " ";
private Cassandra.Client thriftClient = null;
private CliSessionState sessionState = null;
@ -244,6 +249,9 @@ public class CliClient
case CliParser.NODE_SHOW_KEYSPACES:
executeShowKeySpaces();
break;
case CliParser.NODE_SHOW_SCHEMA:
executeShowSchema(tree);
break;
case CliParser.NODE_DESCRIBE_TABLE:
executeDescribeKeySpace(tree);
break;
@ -1249,7 +1257,7 @@ public class CliClient
cfDef.setReplicate_on_write(Boolean.parseBoolean(mValue));
break;
case ROW_CACHE_PROVIDER:
cfDef.setRow_cache_provider(mValue);
cfDef.setRow_cache_provider(CliUtils.unescapeSQLString(mValue));
break;
case KEY_VALIDATION_CLASS:
cfDef.setKey_validation_class(CliUtils.unescapeSQLString(mValue));
@ -1572,6 +1580,187 @@ public class CliClient
}
}
// SHOW SCHEMA
private void executeShowSchema(Tree statement) throws TException, InvalidRequestException
{
if (!CliMain.isConnected())
return;
final List<KsDef> keyspaces = thriftClient.describe_keyspaces();
Collections.sort(keyspaces, new KsDefNamesComparator());
final String keyspaceName = (statement.getChildCount() == 0)
? keySpace
: CliCompiler.getKeySpace(statement, keyspaces);
Iterator<KsDef> ksIter;
if (keyspaceName != null)
ksIter = Collections2.filter(keyspaces, new Predicate<KsDef>()
{
public boolean apply(KsDef ksDef)
{
return keyspaceName.equals(ksDef.name);
}
}).iterator();
else
ksIter = keyspaces.iterator();
final StringBuilder sb = new StringBuilder();
while (ksIter.hasNext())
showKeyspace(sb, ksIter.next());
sessionState.out.printf(sb.toString());
}
/**
* Creates a CLI script to create the Keyspace it's Column Families
* @param sb StringBuilder to write to.
* @param ksDef KsDef to create the cli script for.
*/
private void showKeyspace(StringBuilder sb, KsDef ksDef)
{
sb.append("create keyspace " + ksDef.name);
if (ksDef.isSetReplication_factor())
writeAttr(sb, false, "replication_factor", ksDef.getReplication_factor());
writeAttr(sb, true, "placement_strategy", normaliseType(ksDef.strategy_class, "org.apache.cassandra.locator"));
if (ksDef.strategy_options != null && !ksDef.strategy_options.isEmpty())
{
final StringBuilder opts = new StringBuilder();
opts.append("[{");
String prefix = "";
for (Map.Entry<String, String> opt : ksDef.strategy_options.entrySet())
{
opts.append(prefix + CliUtils.escapeSQLString(opt.getKey()) + " : " + CliUtils.escapeSQLString(opt.getValue()));
prefix = ", ";
}
opts.append("}]");
writeAttrRaw(sb, false, "strategy_options", opts.toString());
}
sb.append(";" + NEWLINE);
sb.append(NEWLINE);
sb.append("use " + ksDef.name + ";");
sb.append(NEWLINE);
sb.append(NEWLINE);
Collections.sort(ksDef.cf_defs, new CfDefNamesComparator());
for (CfDef cfDef : ksDef.cf_defs)
showColumnFamily(sb, cfDef);
sb.append(NEWLINE);
sb.append(NEWLINE);
}
/**
* Creates a CLI script for the CfDef including meta data to the supplied StringBuilder.
* @param sb
* @param cfDef
*/
private void showColumnFamily(StringBuilder sb, CfDef cfDef)
{
sb.append("create column family " + CliUtils.escapeSQLString(cfDef.name));
writeAttr(sb, true, "column_type", cfDef.column_type);
writeAttr(sb, false, "comparator", normaliseType(cfDef.comparator_type, "org.apache.cassandra.db.marshal"));
if (cfDef.column_type == "Super")
writeAttr(sb, false, "subcomparator", normaliseType(cfDef.subcomparator_type, "org.apache.cassandra.db.marshal"));
if (!StringUtils.isEmpty(cfDef.default_validation_class))
writeAttr(sb, false, "default_validation_class",
normaliseType(cfDef.default_validation_class, "org.apache.cassandra.db.marshal"));
writeAttr(sb, false, "key_validation_class",
normaliseType(cfDef.key_validation_class, "org.apache.cassandra.db.marshal"));
writeAttr(sb, false, "memtable_operations", cfDef.memtable_operations_in_millions);
writeAttr(sb, false, "memtable_throughput", cfDef.memtable_throughput_in_mb);
writeAttr(sb, false, "memtable_flush_after", cfDef.memtable_flush_after_mins);
writeAttr(sb, false, "rows_cached", cfDef.row_cache_size);
writeAttr(sb, false, "row_cache_save_period", cfDef.row_cache_save_period_in_seconds);
writeAttr(sb, false, "keys_cached", cfDef.key_cache_size);
writeAttr(sb, false, "key_cache_save_period", cfDef.key_cache_save_period_in_seconds);
writeAttr(sb, false, "read_repair_chance", cfDef.read_repair_chance);
writeAttr(sb, false, "gc_grace", cfDef.gc_grace_seconds);
writeAttr(sb, false, "min_compaction_threshold", cfDef.min_compaction_threshold);
writeAttr(sb, false, "max_compaction_threshold", cfDef.max_compaction_threshold);
writeAttr(sb, false, "replicate_on_write", cfDef.replicate_on_write);
writeAttr(sb, false, "row_cache_provider", normaliseType(cfDef.row_cache_provider, "org.apache.cassandra.cache"));
if (!StringUtils.isEmpty(cfDef.comment))
writeAttr(sb, false, "comment", cfDef.comment);
if (!cfDef.column_metadata.isEmpty())
{
StringBuilder colSb = new StringBuilder();
colSb.append("[");
boolean first = true;
for (ColumnDef colDef : cfDef.column_metadata)
{
if (!first)
colSb.append(",");
first = false;
showColumnMeta(colSb, cfDef, colDef);
}
colSb.append("]");
writeAttrRaw(sb, false, "column_metadata", colSb.toString());
}
sb.append(";");
sb.append(NEWLINE);
sb.append(NEWLINE);
}
/**
* Writes the supplied ColumnDef to the StringBuilder as a cli script.
* @param sb
* @param cfDef
* @param colDef
*/
private void showColumnMeta(StringBuilder sb, CfDef cfDef, ColumnDef colDef)
{
sb.append(NEWLINE + TAB + TAB + "{");
final AbstractType comparator = getFormatType((cfDef.column_type == "Super")
? cfDef.subcomparator_type
: cfDef.comparator_type);
sb.append("column_name : '" + CliUtils.escapeSQLString(comparator.getString(colDef.name)) + "'," + NEWLINE);
String validationClass = normaliseType(colDef.validation_class, "org.apache.cassandra.db.marshal");
sb.append(TAB + TAB + "validation_class : " + CliUtils.escapeSQLString(validationClass));
if (colDef.isSetIndex_name())
{
sb.append("," + NEWLINE);
sb.append(TAB + TAB + "index_name : '" + CliUtils.escapeSQLString(colDef.index_name) + "'," + NEWLINE);
sb.append(TAB + TAB + "index_type : " + CliUtils.escapeSQLString(Integer.toString(colDef.index_type.getValue())));
}
sb.append("}");
}
private String normaliseType(String path, String expectedPackage)
{
if (path.startsWith(expectedPackage))
return path.substring(expectedPackage.length() + 1);
return path;
}
private void writeAttr(StringBuilder sb, boolean first, String name, Boolean value)
{
writeAttrRaw(sb, first, name, value.toString());
}
private void writeAttr(StringBuilder sb, boolean first, String name, Number value)
{
writeAttrRaw(sb, first, name, value.toString());
}
private void writeAttr(StringBuilder sb, boolean first, String name, String value)
{
writeAttrRaw(sb, first, name, "'" + CliUtils.escapeSQLString(value) + "'");
}
private void writeAttrRaw(StringBuilder sb, boolean first, String name, String value)
{
sb.append(NEWLINE + TAB);
sb.append(first ? "with " : "and ");
sb.append(name + " = ");
sb.append(value);
}
/**
* Returns true if this.keySpace is set, false otherwise
* @return boolean

View File

@ -29,6 +29,7 @@ public class CliCompleter extends SimpleCompletor
"quit",
"show cluster name",
"show keyspaces",
"show schema",
"show api version",
"create keyspace",
"create column family",
@ -45,6 +46,7 @@ public class CliCompleter extends SimpleCompletor
"help quit",
"help show cluster name",
"help show keyspaces",
"help show schema",
"help show api version",
"help create keyspace",
"help create column family",

View File

@ -96,7 +96,7 @@ public class StorageProxy implements StorageProxyMBean
public void apply(IMutation mutation, Multimap<InetAddress, InetAddress> hintedEndpoints, IWriteResponseHandler responseHandler, String localDataCenter, ConsistencyLevel consistency_level) throws IOException
{
assert mutation instanceof RowMutation;
sendToHintedEndpoints((RowMutation) mutation, hintedEndpoints, responseHandler, localDataCenter, true, consistency_level);
sendToHintedEndpoints((RowMutation) mutation, hintedEndpoints, responseHandler, localDataCenter, consistency_level);
}
};
@ -110,7 +110,11 @@ public class StorageProxy implements StorageProxyMBean
{
public void apply(IMutation mutation, Multimap<InetAddress, InetAddress> hintedEndpoints, IWriteResponseHandler responseHandler, String localDataCenter, ConsistencyLevel consistency_level) throws IOException
{
applyCounterMutation(mutation, hintedEndpoints, responseHandler, localDataCenter, consistency_level, false);
if (logger.isDebugEnabled())
logger.debug("insert writing local & replicate " + mutation.toString(true));
Runnable runnable = counterWriteTask(mutation, hintedEndpoints, responseHandler, localDataCenter, consistency_level);
runnable.run();
}
};
@ -118,7 +122,11 @@ public class StorageProxy implements StorageProxyMBean
{
public void apply(IMutation mutation, Multimap<InetAddress, InetAddress> hintedEndpoints, IWriteResponseHandler responseHandler, String localDataCenter, ConsistencyLevel consistency_level) throws IOException
{
applyCounterMutation(mutation, hintedEndpoints, responseHandler, localDataCenter, consistency_level, true);
if (logger.isDebugEnabled())
logger.debug("insert writing local & replicate " + mutation.toString(true));
Runnable runnable = counterWriteTask(mutation, hintedEndpoints, responseHandler, localDataCenter, consistency_level);
StageManager.getStage(Stage.MUTATION).execute(runnable);
}
};
}
@ -218,7 +226,7 @@ public class StorageProxy implements StorageProxyMBean
return ss.getTokenMetadata().getWriteEndpoints(StorageService.getPartitioner().getToken(key), table, naturalEndpoints);
}
private static void sendToHintedEndpoints(final RowMutation rm, Multimap<InetAddress, InetAddress> hintedEndpoints, IWriteResponseHandler responseHandler, String localDataCenter, boolean insertLocalMessages, ConsistencyLevel consistency_level)
private static void sendToHintedEndpoints(final RowMutation rm, Multimap<InetAddress, InetAddress> hintedEndpoints, IWriteResponseHandler responseHandler, String localDataCenter, ConsistencyLevel consistency_level)
throws IOException
{
// Multimap that holds onto all the messages and addresses meant for a specific datacenter
@ -237,8 +245,7 @@ public class StorageProxy implements StorageProxyMBean
// unhinted writes
if (destination.equals(FBUtilities.getBroadcastAddress()))
{
if (insertLocalMessages)
insertLocal(rm, responseHandler);
insertLocal(rm, responseHandler);
}
else
{
@ -425,13 +432,9 @@ public class StorageProxy implements StorageProxyMBean
return performWrite(cm, cm.consistency(), localDataCenter, counterWriteOnCoordinatorPerformer);
}
private static void applyCounterMutation(final IMutation mutation, final Multimap<InetAddress, InetAddress> hintedEndpoints, final IWriteResponseHandler responseHandler, final String localDataCenter, final ConsistencyLevel consistency_level, boolean executeOnMutationStage)
private static Runnable counterWriteTask(final IMutation mutation, final Multimap<InetAddress, InetAddress> hintedEndpoints, final IWriteResponseHandler responseHandler, final String localDataCenter, final ConsistencyLevel consistency_level)
{
// we apply locally first, then send it to other replica
if (logger.isDebugEnabled())
logger.debug("insert writing local & replicate " + mutation.toString(true));
Runnable runnable = new DroppableRunnable(StorageService.Verb.MUTATION)
return new DroppableRunnable(StorageService.Verb.MUTATION)
{
public void runMayThrow() throws IOException
{
@ -440,10 +443,11 @@ public class StorageProxy implements StorageProxyMBean
// apply mutation
cm.apply();
responseHandler.response(null);
if (cm.shouldReplicateOnWrite())
// then send to replicas, if any
hintedEndpoints.removeAll(FBUtilities.getLocalAddress());
if (cm.shouldReplicateOnWrite() && !hintedEndpoints.isEmpty())
{
// We do the replication on another stage because it involves a read (see CM.makeReplicationMutation)
// and we want to avoid blocking too much the MUTATION stage
@ -452,16 +456,12 @@ public class StorageProxy implements StorageProxyMBean
public void runMayThrow() throws IOException
{
// send mutation to other replica
sendToHintedEndpoints(cm.makeReplicationMutation(), hintedEndpoints, responseHandler, localDataCenter, false, consistency_level);
sendToHintedEndpoints(cm.makeReplicationMutation(), hintedEndpoints, responseHandler, localDataCenter, consistency_level);
}
});
}
}
};
if (executeOnMutationStage)
StageManager.getStage(Stage.MUTATION).execute(runnable);
else
runnable.run();
}
/**

View File

@ -596,7 +596,7 @@ public class StorageService implements IEndpointStateChangeSubscriber, StorageSe
for (InetAddress endpoint: entry.getValue())
{
if (endpoint.equals(FBUtilities.getLocalAddress()))
rpcaddrs.add(DatabaseDescriptor.getRpcAddress().toString());
rpcaddrs.add(DatabaseDescriptor.getRpcAddress().getHostAddress());
else
rpcaddrs.add(Gossiper.instance.getEndpointStateForEndpoint(endpoint).getApplicationState(ApplicationState.RPC_ADDRESS).value);
}

View File

@ -52,6 +52,7 @@ help: |
show api version Show the server API version.
show cluster name Show the cluster name.
show keyspaces Show all keyspaces and their column families.
show schema Show a cli script to create keyspaces and column families.
truncate Drop the data in a column family.
update column family Update the settings for a column family.
update keyspace Update the settings for a keyspace.
@ -116,7 +117,8 @@ commands:
use Keyspace1 user 'badpasswd';
- name: NODE_DESCRIBE_TABLE
help: |
describe keyspace (<keyspace>)?;
describe keyspace;
describe keyspace <keyspace>;
Describes the settings for the current or named keyspace, and the settings
for all column families in the keyspace.
@ -126,7 +128,7 @@ commands:
Examples:
describe keyspace;
describe keyspace system;
describe keyspace Keyspace1;
- name: NODE_DESCRIBE_CLUSTER
help: |
describe cluster;
@ -177,6 +179,22 @@ commands:
Examples:
show keyspaces;
- name: NODE_SHOW_SCHEMA
help: |
show schema;
show schema <keyspace>;
Creates a CLI script to create the current, specified or all keyspaces
and their column families.
Optional Parameters:
- keyspace: Name of the keyspace to create the script for. If omitted
the current keyspace is used, if there is no current keyspace all
keyspaces are considered.
Examples:
show schema;
show schema Keyspace1;
- name: NODE_ADD_KEYSPACE
help: |
create keyspace <keyspace>;

View File

@ -168,6 +168,7 @@ public class CliTest extends CleanupHelper
"help QUIT",
"help show cluster name",
"help show keyspaces",
"help show schema",
"help show api version",
"help create keyspace",
"HELP update KEYSPACE",
@ -183,7 +184,9 @@ public class CliTest extends CleanupHelper
"HELP TRUNCATE",
"help assume",
"HELP",
"?"
"?",
"show schema",
"show schema TestKeySpace"
};
@Test