merge from 0.8

git-svn-id: https://svn.apache.org/repos/asf/cassandra/trunk@1137777 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jonathan Ellis 2011-06-20 20:54:24 +00:00
commit f491265fc5
32 changed files with 851 additions and 149 deletions

View File

@ -8,6 +8,14 @@
* Fixed the ability to set compaction strategy in cli using create column family command (CASSANDRA-2778)
* Add startup flag to renew counter node id (CASSANDRA-2788)
0.8.2
* fix cache mbean getSize (CASSANDRA-2781)
* Add Date, Float, Double, and Boolean types (CASSANDRA-2530)
* fix repair hanging if a neighbor has nothing to send (CASSANDRA-2797)
* add jamm agent to cassandra.bat (CASSANDRA-2787)
0.8.1
* CQL:
- support for insert, delete in BATCH (CASSANDRA-2537)
@ -15,7 +23,6 @@
- timestamp support for INSERT, UPDATE, and BATCH (CASSANDRA-2555)
- TTL support (CASSANDRA-2476)
- counter support (CASSANDRA-2473)
- improve JDBC spec compliance (CASSANDRA-2720)
- ALTER COLUMNFAMILY (CASSANDRA-1709)
- DROP INDEX (CASSANDRA-2617)
- add SCHEMA/TABLE as aliases for KS/CF (CASSANDRA-2743)
@ -58,6 +65,7 @@
by nio sockets (CASSANDRA-2654)
* restrict repair streaming to specific columnfamilies (CASSANDRA-2280)
* fix nodetool ring use with Ec2Snitch (CASSANDRA-2733)
* fix inconsistency window during bootstrap (CASSANDRA-833)
* fix removing columns and subcolumns that are supressed by a row or
supercolumn tombstone during replica resolution (CASSANDRA-2590)
* support sstable2json against snapshot sstables (CASSANDRA-2386)
@ -68,7 +76,14 @@
* avoid skipping rows in scrub for counter column family (CASSANDRA-2759)
* fix ConcurrentModificationException in repair when dealing with 0.7 node
(CASSANDRA-2767)
* use threadsafe collections for StreamInSession (CASSANDRA-2766)
* avoid infinite loop when creating merkle tree (CASSANDRA-2758)
* avoids unmarking compacting sstable prematurely in cleanup (CASSANDRA-2769)
* fix NPE when the commit log is bypassed (CASSANDRA-2718)
* don't throw an exception in SS.isRPCServerRunning (CASSANDRA-2721)
* make stress.jar executable (CASSANDRA-2744)
* add daemon mode to java stress (CASSANDRA-2267)
* expose the DC and rack of a node through JMX and nodetool ring (CASSANDRA-2531)
0.8.0-final
@ -175,7 +190,8 @@
* add key type information and alias (CASSANDRA-2311, 2396)
* cli no longer divides read_repair_chance by 100 (CASSANDRA-2458)
* made CompactionInfo.getTaskType return an enum (CASSANDRA-2482)
* add a server-wide cap on measured memtable memory usage (CASSANDRA-2006)
* add a server-wide cap on measured memtable memory usage and aggressively
flush to keep under that threshold (CASSANDRA-2006)
* add unified UUIDType (CASSANDRA-2233)

View File

@ -7,6 +7,31 @@ Upgrading
sstableloader tool instead.
0.8.1
=====
Upgrading
---------
- 0.8.1 is backwards compatible with 0.8, upgrade can be achieved by a
simple rolling restart.
- If upgrading for earlier version (0.7), please refer to the 0.8 section
for instructions.
Features
--------
- Numerous additions/improvements to CQL (support for counters, TTL, batch
inserts/deletes, index dropping, ...).
- Add two new AbstractTypes (comparator) to support compound keys
(CompositeType and DynamicCompositeType), as well as a ReverseType to
reverse the order of any existing comparator.
- New option to bypass the commit log on some keyspaces (for advanced
users).
Tools
-----
- Add new data bulk loading utility (sstableloader).
0.8
===

View File

@ -24,6 +24,7 @@ if NOT DEFINED JAVA_HOME goto err
REM ***** JAVA options *****
set JAVA_OPTS=^
-ea^
-javaagent:%CASSANDRA_HOME%\lib\jamm-0.2.2.jar^
-Xms1G^
-Xmx1G^
-XX:+HeapDumpOnOutOfMemoryError^

View File

@ -25,8 +25,8 @@
<property name="debuglevel" value="source,lines,vars"/>
<!-- default version and SCM information (we need the default SCM info as people may checkout with git-svn) -->
<property name="base.version" value="0.8.0"/>
<property name="scm.default.path" value="cassandra/branches/cassandra-0.7"/>
<property name="base.version" value="0.8.1"/>
<property name="scm.default.path" value="cassandra/branches/cassandra-0.8"/>
<property name="scm.default.connection" value="scm:svn:http://svn.apache.org/repos/asf/${scm.default.path}"/>
<property name="scm.default.developerConnection" value="scm:svn:https://svn.apache.org/repos/asf/${scm.default.path}"/>
<property name="scm.default.url" value="http://svn.apache.org/viewvc/${scm.default.path}"/>

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
cassandra (0.8.1) unstable; urgency=low
* New release
-- Sylvain Lebresne <slebresne@apache.org> Thu, 16 Jun 2011 09:37:27 +0200
cassandra (0.8.0) unstable; urgency=low
* New release

2
debian/rules vendored
View File

@ -40,8 +40,6 @@ install: build
usr/share/cassandra
dh_install build/apache-cassandra-thrift-$(VERSION).jar \
usr/share/cassandra
dh_install build/apache-cassandra-cql-*.jar \
usr/share/cassandra
dh_link usr/share/cassandra/apache-cassandra-$(VERSION).jar \
usr/share/cassandra/apache-cassandra.jar

View File

@ -136,13 +136,13 @@ public class WordCount extends Configured implements Tool
private static Mutation getMutation(Text word, int sum)
{
Column c = new Column();
c.name = ByteBuffer.wrap(Arrays.copyOf(word.getBytes(), word.getLength()));
c.value = ByteBufferUtil.bytes(String.valueOf(sum));
c.timestamp = System.currentTimeMillis() * 1000;
c.setName(Arrays.copyOf(word.getBytes(), word.getLength()));
c.setValue(ByteBufferUtil.bytes(String.valueOf(sum)));
c.setTimestamp(System.currentTimeMillis());
Mutation m = new Mutation();
m.column_or_supercolumn = new ColumnOrSuperColumn();
m.column_or_supercolumn.column = c;
m.setColumn_or_supercolumn(new ColumnOrSuperColumn());
m.column_or_supercolumn.setColumn(c);
return m;
}
}

View File

@ -108,6 +108,11 @@ public class InstrumentingCache<K, V> implements InstrumentingCacheMBean
return map.size();
}
public int getSize()
{
return size();
}
public long getHits()
{
return hits.get();

View File

@ -25,7 +25,7 @@ public interface InstrumentingCacheMBean
{
public int getCapacity();
public void setCapacity(int capacity);
public int size();
public int getSize();
/** total request count since cache creation */
public long getRequests();

View File

@ -265,6 +265,7 @@ public class CliClient
break;
case CliParser.NODE_CONSISTENCY_LEVEL:
executeConsistencyLevelStatement(tree);
break;
case CliParser.NODE_THRIFT_INCR:
executeIncr(tree, 1L);
break;
@ -2087,17 +2088,6 @@ public class CliClient
return getBytesAccordingToType(superColumn, getFormatType(comparatorClass));
}
/**
* Converts column name into byte[] according to comparator type
* @param superColumn - sub-column name from parser
* @param columnFamily - column family name from parser
* @return bytes[] - into which column name was converted according to comparator type
*/
private byte[] subColumnNameAsByteArray(String superColumn, String columnFamily)
{
return TBaseHelper.byteBufferToByteArray(subColumnNameAsBytes(superColumn, columnFamily));
}
/**
* Converts sub-column name into byte[] according to comparator type
* @param superColumn - sub-column name from parser

View File

@ -427,11 +427,11 @@ dropColumnFamilyStatement returns [String cfam]
;
comparatorType
: 'bytea' | 'ascii' | 'text' | 'varchar' | 'int' | 'varint' | 'bigint' | 'uuid' | 'counter'
: 'bytea' | 'ascii' | 'text' | 'varchar' | 'int' | 'varint' | 'bigint' | 'uuid' | 'counter' | 'boolean' | 'date' | 'float' | 'double'
;
term returns [Term item]
: ( t=K_KEY | t=STRING_LITERAL | t=INTEGER | t=UUID | t=IDENT ) { $item = new Term($t.text, $t.type); }
: ( t=K_KEY | t=STRING_LITERAL | t=INTEGER | t=UUID | t=IDENT | t=FLOAT) { $item = new Term($t.text, $t.type); }
;
termList returns [List<Term> items]

View File

@ -72,6 +72,10 @@ public class CreateColumnFamilyStatement
comparators.put("bigint", "LongType");
comparators.put("uuid", "UUIDType");
comparators.put("counter", "CounterColumnType");
comparators.put("boolean", "BooleanType");
comparators.put("date", "DateType");
comparators.put("float", "FloatType");
comparators.put("double", "DoubleType");
keywords.add(KW_COMPARATOR);
keywords.add(KW_COMMENT);

View File

@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.marshal.FloatType;
import org.apache.cassandra.db.marshal.IntegerType;
import org.apache.cassandra.db.marshal.LexicalUUIDType;
import org.apache.cassandra.db.marshal.MarshalException;
@ -107,6 +108,8 @@ public class Term
// we specifically want the Lexical class here, not "UUIDType," because we're supposed to have
// a uuid-shaped string here, and UUIDType also accepts integer or date strings (and turns them into version 1 uuids).
return LexicalUUIDType.instance.fromString(text);
case FLOAT:
return FloatType.instance.fromString(text);
}
// FIXME: handle scenario that should never happen
@ -132,7 +135,7 @@ public class Term
enum TermType
{
STRING, INTEGER, UUID;
STRING, INTEGER, UUID, FLOAT;
static TermType forInt(int type)
{
@ -141,7 +144,9 @@ enum TermType
else if (type == CqlParser.INTEGER)
return INTEGER;
else if (type == CqlParser.UUID)
return UUID;
return UUID;
else if (type == CqlParser.FLOAT)
return FLOAT;
// FIXME: handled scenario that should never occur.
return null;

View File

@ -1,4 +1,25 @@
package org.apache.cassandra.db;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.io.DataOutput;
import java.io.IOException;

View File

@ -73,9 +73,9 @@ public class ReplayPosition implements Comparable<ReplayPosition>
public int compare(ReplayPosition o1, ReplayPosition o2)
{
if (o1.segment != o2.segment)
return new Long(o1.segment).compareTo(o2.segment);
return Long.valueOf(o1.segment).compareTo(o2.segment);
return new Integer(o1.position).compareTo(o2.position);
return Integer.valueOf(o1.position).compareTo(o2.position);
}
};

View File

@ -652,56 +652,50 @@ public class CompactionManager implements CompactionManagerMBean
logger.debug("Expected bloom filter size : " + expectedBloomFilterSize);
SSTableWriter writer = null;
logger.info("Cleaning up " + sstable);
// Calculate the expected compacted filesize
long expectedRangeFileSize = cfs.getExpectedCompactedFileSize(Arrays.asList(sstable)) / 2;
String compactionFileLocation = table.getDataFileLocation(expectedRangeFileSize);
if (compactionFileLocation == null)
throw new IOException("disk full");
SSTableScanner scanner = sstable.getDirectScanner(CompactionIterator.FILE_BUFFER_SIZE);
SortedSet<ByteBuffer> indexedColumns = cfs.getIndexedColumns();
CleanupInfo ci = new CleanupInfo(sstable, scanner);
executor.beginCompaction(ci);
try
{
logger.info("Cleaning up " + sstable);
// Calculate the expected compacted filesize
long expectedRangeFileSize = cfs.getExpectedCompactedFileSize(Arrays.asList(sstable)) / 2;
String compactionFileLocation = table.getDataFileLocation(expectedRangeFileSize);
if (compactionFileLocation == null)
throw new IOException("disk full");
SSTableScanner scanner = sstable.getDirectScanner(CompactionIterator.FILE_BUFFER_SIZE);
SortedSet<ByteBuffer> indexedColumns = cfs.getIndexedColumns();
CleanupInfo ci = new CleanupInfo(sstable, scanner);
executor.beginCompaction(ci);
try
while (scanner.hasNext())
{
while (scanner.hasNext())
SSTableIdentityIterator row = (SSTableIdentityIterator) scanner.next();
if (Range.isTokenInRanges(row.getKey().token, ranges))
{
SSTableIdentityIterator row = (SSTableIdentityIterator) scanner.next();
if (Range.isTokenInRanges(row.getKey().token, ranges))
writer = maybeCreateWriter(cfs, compactionFileLocation, expectedBloomFilterSize, writer, Collections.singletonList(sstable));
writer.append(controller.getCompactedRow(row));
totalkeysWritten++;
}
else
{
cfs.invalidateCachedRow(row.getKey());
if (!indexedColumns.isEmpty() || isCommutative)
{
writer = maybeCreateWriter(cfs, compactionFileLocation, expectedBloomFilterSize, writer, Collections.singletonList(sstable));
writer.append(controller.getCompactedRow(row));
totalkeysWritten++;
}
else
{
cfs.invalidateCachedRow(row.getKey());
if (!indexedColumns.isEmpty() || isCommutative)
while (row.hasNext())
{
while (row.hasNext())
{
IColumn column = row.next();
if (column instanceof CounterColumn)
renewer.maybeRenew((CounterColumn) column);
if (indexedColumns.contains(column.name()))
Table.cleanupIndexEntry(cfs, row.getKey().key, column);
}
IColumn column = row.next();
if (column instanceof CounterColumn)
renewer.maybeRenew((CounterColumn) column);
if (indexedColumns.contains(column.name()))
Table.cleanupIndexEntry(cfs, row.getKey().key, column);
}
}
}
}
finally
{
scanner.close();
executor.finishCompaction(ci);
}
}
finally
{
cfs.getDataTracker().unmarkCompacting(Arrays.asList(sstable));
scanner.close();
executor.finishCompaction(ci);
}
List<SSTableReader> results = new ArrayList<SSTableReader>();

View File

@ -0,0 +1,136 @@
package org.apache.cassandra.db.marshal;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.nio.ByteBuffer;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class BooleanType extends AbstractType<Boolean>
{
public static final BooleanType instance = new BooleanType();
BooleanType() {} // singleton
public Boolean compose(ByteBuffer bytes)
{
byte value = bytes.get(bytes.position());
return Boolean.valueOf(value ==0 ? false:true);
}
public ByteBuffer decompose(Boolean value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER
: value ? ByteBuffer.wrap(new byte[]{1}) // true
: ByteBuffer.wrap(new byte[]{0}); // false
}
public int compare(ByteBuffer o1, ByteBuffer o2)
{
if ((o1 == null) || (o1.remaining() != 1))
return ((o2 == null) || (o2.remaining() != 1)) ? 0 : -1;
if ((o2 == null) || (o2.remaining() != 1))
return 1;
return o1.compareTo(o2);
}
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return Boolean.FALSE.toString();
}
if (bytes.remaining() != 1)
{
throw new MarshalException("A boolean is stored in exactly 1 byte: "+bytes.remaining());
}
byte value = bytes.get(bytes.position());
return value ==0 ? Boolean.FALSE.toString(): Boolean.TRUE.toString();
}
public String toString(Boolean b)
{
return b.toString();
}
public ByteBuffer fromString(String source) throws MarshalException
{
if (source.isEmpty()|| source.equalsIgnoreCase(Boolean.FALSE.toString()))
return decompose(false);
if (source.equalsIgnoreCase(Boolean.TRUE.toString()))
return decompose(true);
throw new MarshalException(String.format("unable to make boolean from '%s'", source));
}
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 1 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 1 or 0 byte value (%d)", bytes.remaining()));
}
public Class<Boolean> getType()
{
return Boolean.class;
}
public boolean isSigned()
{
return false;
}
public boolean isCaseSensitive()
{
return false;
}
public boolean isCurrency()
{
return false;
}
public int getPrecision(Boolean obj)
{
return -1;
}
public int getScale(Boolean obj)
{
return -1;
}
public int getJdbcType()
{
return Types.BOOLEAN;
}
public boolean needsQuotes()
{
return false;
}
}

View File

@ -0,0 +1,178 @@
package org.apache.cassandra.db.marshal;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import static org.apache.cassandra.db.marshal.TimeUUIDType.iso8601Patterns;
import java.nio.ByteBuffer;
import java.sql.Types;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.commons.lang.time.DateUtils;
public class DateType extends AbstractType<Date>
{
public static final DateType instance = new DateType();
static final String DEFAULT_FORMAT = iso8601Patterns[3];
static final SimpleDateFormat FORMATTER = new SimpleDateFormat(DEFAULT_FORMAT);
DateType() {} // singleton
public Date compose(ByteBuffer bytes)
{
return new Date(ByteBufferUtil.toLong(bytes));
}
public ByteBuffer decompose(Date value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER
: ByteBufferUtil.bytes(value.getTime());
}
public int compare(ByteBuffer o1, ByteBuffer o2)
{
if (o1.remaining() == 0)
{
return o2.remaining() == 0 ? 0 : -1;
}
if (o2.remaining() == 0)
{
return 1;
}
return ByteBufferUtil.compareUnsigned(o1, o2);
}
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
if (bytes.remaining() != 8)
{
throw new MarshalException("A date is exactly 8 bytes (stored as a long): "+bytes.remaining());
}
// uses ISO-8601 formatted string
return FORMATTER.format(new Date(bytes.getLong(bytes.position())));
}
public String toString(Date d)
{
// uses ISO-8601 formatted string
return FORMATTER.format(d);
}
public ByteBuffer fromString(String source) throws MarshalException
{
// Return an empty ByteBuffer for an empty string.
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
long millis;
ByteBuffer idBytes = null;
if (source.toLowerCase().equals("now"))
{
millis = System.currentTimeMillis();
idBytes = ByteBufferUtil.bytes(millis);
}
// Milliseconds since epoch?
else if (source.matches("^\\d+$"))
{
try
{
idBytes = ByteBufferUtil.bytes(Long.parseLong(source));
}
catch (NumberFormatException e)
{
throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
}
}
// Last chance, attempt to parse as date-time string
else
{
try
{
millis = DateUtils.parseDate(source, iso8601Patterns).getTime();
idBytes = ByteBufferUtil.bytes(millis);
}
catch (ParseException e1)
{
throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
}
}
return idBytes;
}
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte long for date (%d)", bytes.remaining()));
}
public Class<Date> getType()
{
return Date.class;
}
public boolean isSigned()
{
return false;
}
public boolean isCaseSensitive()
{
return false;
}
public boolean isCurrency()
{
return false;
}
public int getPrecision(Date obj)
{
return -1;
}
public int getScale(Date obj)
{
return -1;
}
public int getJdbcType()
{
return Types.DATE;
}
public boolean needsQuotes()
{
return false;
}
}

View File

@ -0,0 +1,143 @@
package org.apache.cassandra.db.marshal;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.nio.ByteBuffer;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class DoubleType extends AbstractType<Double>
{
public static final DoubleType instance = new DoubleType();
DoubleType() {} // singleton
public Double compose(ByteBuffer bytes)
{
return ByteBufferUtil.toDouble(bytes);
}
public ByteBuffer decompose(Double value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
{
if (o1.remaining() == 0)
{
return o2.remaining() == 0 ? 0 : -1;
}
if (o2.remaining() == 0)
{
return 1;
}
return compose(o1).compareTo(compose(o2));
}
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
if (bytes.remaining() != 8)
{
throw new MarshalException("A double is exactly 8 bytes : "+bytes.remaining());
}
return compose(bytes).toString();
}
public String toString(Double d)
{
return d.toString();
}
public ByteBuffer fromString(String source) throws MarshalException
{
// Return an empty ByteBuffer for an empty string.
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
Double d;
try
{
d = Double.parseDouble(source);
}
catch (NumberFormatException e1)
{
throw new MarshalException(String.format("unable to coerce '%s' to a double", source), e1);
}
return decompose(d);
}
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte value for a double (%d)", bytes.remaining()));
}
public Class<Double> getType()
{
return Double.class;
}
public boolean isSigned()
{
return true;
}
public boolean isCaseSensitive()
{
return false;
}
public boolean isCurrency()
{
return false;
}
public int getPrecision(Double obj) // see: http://teaching.idallen.org/dat2343/09f/notes/10FloatingPoint.htm
{
return 15;
}
public int getScale(Double obj) // see: http://teaching.idallen.org/dat2343/09f/notes/10FloatingPoint.htm
{
return 300;
}
public int getJdbcType()
{
return Types.DOUBLE;
}
public boolean needsQuotes()
{
return false;
}
}

View File

@ -0,0 +1,144 @@
package org.apache.cassandra.db.marshal;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.nio.ByteBuffer;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class FloatType extends AbstractType<Float>
{
public static final FloatType instance = new FloatType();
FloatType() {} // singleton
public Float compose(ByteBuffer bytes)
{
return ByteBufferUtil.toFloat(bytes);
}
public ByteBuffer decompose(Float value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
{
if (o1.remaining() == 0)
{
return o2.remaining() == 0 ? 0 : -1;
}
if (o2.remaining() == 0)
{
return 1;
}
return compose(o1).compareTo(compose(o2));
}
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
if (bytes.remaining() != 4)
{
throw new MarshalException("A float is exactly 4 bytes : "+bytes.remaining());
}
return compose(bytes).toString();
}
public String toString(Float d)
{
return d.toString();
}
public ByteBuffer fromString(String source) throws MarshalException
{
// Return an empty ByteBuffer for an empty string.
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
Float f;
try
{
f = Float.parseFloat(source);
}
catch (NumberFormatException e1)
{
throw new MarshalException(String.format("unable to coerce '%s' to a float", source), e1);
}
return ByteBufferUtil.bytes(f);
}
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 4 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 4 or 0 byte value for a float (%d)", bytes.remaining()));
}
public Class<Float> getType()
{
return Float.class;
}
public boolean isSigned()
{
return true;
}
public boolean isCaseSensitive()
{
return false;
}
public boolean isCurrency()
{
return false;
}
public int getPrecision(Float obj) // see: http://teaching.idallen.org/dat2343/09f/notes/10FloatingPoint.htm
{
return 7;
}
public int getScale(Float obj) // see: http://teaching.idallen.org/dat2343/09f/notes/10FloatingPoint.htm
{
return 40;
}
public int getJdbcType()
{
return Types.FLOAT;
}
public boolean needsQuotes()
{
return false;
}
}

View File

@ -257,7 +257,7 @@ class ArrivalWindow
}
// see CASSANDRA-2597 for an explanation of the math at work here.
double phi(long tnow)
synchronized double phi(long tnow)
{
int size = arrivalIntervals_.size();
double t = tnow - tLast_;

View File

@ -190,7 +190,7 @@ public class Gossiper implements IFailureDetectionEventListener
public void setVersion(InetAddress address, int version)
{
Integer old = versions.put(address, version);
versions.put(address, version);
}
public Integer getVersion(InetAddress address)
@ -717,7 +717,6 @@ public class Gossiper implements IFailureDetectionEventListener
{
// don't assert here, since if the node restarts the version will go back to zero
int oldVersion = localState.getHeartBeatState().getHeartBeatVersion();
Map<ApplicationState, VersionedValue> localAppStateMap = localState.getApplicationStateMap();
localState.setHeartBeatState(remoteState.getHeartBeatState());
if (logger.isTraceEnabled())

View File

@ -136,26 +136,13 @@ public class FileUtils
}
}
public static void createFile(String directory) throws IOException
{
File file = new File(directory);
if ( !file.exists() )
file.createNewFile();
}
public static boolean isExists(String filename) throws IOException
{
File file = new File(filename);
return file.exists();
}
public static boolean delete(String file)
{
File f = new File(file);
return f.delete();
}
public static boolean delete(List<String> files) throws IOException
public static boolean delete(List<String> files)
{
boolean bVal = true;
for ( int i = 0; i < files.size(); ++i )
@ -172,7 +159,7 @@ public class FileUtils
return bVal;
}
public static void delete(File[] files) throws IOException
public static void delete(File[] files)
{
for ( File file : files )
{

View File

@ -24,18 +24,20 @@ import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import org.apache.cassandra.gms.Gossiper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.db.Table;
import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.net.MessagingService;
import org.apache.cassandra.utils.Pair;
import org.cliffc.high_scale_lib.NonBlockingHashMap;
import org.cliffc.high_scale_lib.NonBlockingHashSet;
/** each context gets its own StreamInSession. So there may be >1 Session per host */
public class StreamInSession
@ -44,11 +46,11 @@ public class StreamInSession
private static ConcurrentMap<Pair<InetAddress, Long>, StreamInSession> sessions = new NonBlockingHashMap<Pair<InetAddress, Long>, StreamInSession>();
private final List<PendingFile> files = new ArrayList<PendingFile>();
private final Set<PendingFile> files = new NonBlockingHashSet<PendingFile>();
private final Pair<InetAddress, Long> context;
private final Runnable callback;
private String table;
private final List<Future<SSTableReader>> buildFutures = new ArrayList<Future<SSTableReader>>();
private final Collection<Future<SSTableReader>> buildFutures = new LinkedBlockingQueue<Future<SSTableReader>>();
private PendingFile current;
private StreamInSession(Pair<InetAddress, Long> context, Runnable callback)

View File

@ -122,15 +122,10 @@ public class StreamOut
{
List<PendingFile> pending = createPendingFiles(sstables, ranges, type);
if (pending.size() > 0)
{
session.addFilesToStream(pending);
session.begin();
}
else
{
session.close();
}
// Even if the list of pending files is empty, we need to initiate the transfer otherwise
// the remote end will hang in cases where this was a requested transfer.
session.addFilesToStream(pending);
session.begin();
}
// called prior to sending anything.

View File

@ -450,7 +450,7 @@ public class NodeCmd
if (keyCacheMBean.getCapacity() > 0)
{
outs.println("\t\tKey cache capacity: " + keyCacheMBean.getCapacity());
outs.println("\t\tKey cache size: " + keyCacheMBean.size());
outs.println("\t\tKey cache size: " + keyCacheMBean.getSize());
outs.println("\t\tKey cache hit rate: " + keyCacheMBean.getRecentHitRate());
}
else
@ -462,7 +462,7 @@ public class NodeCmd
if (rowCacheMBean.getCapacity() > 0)
{
outs.println("\t\tRow cache capacity: " + rowCacheMBean.getCapacity());
outs.println("\t\tRow cache size: " + rowCacheMBean.size());
outs.println("\t\tRow cache size: " + rowCacheMBean.getSize());
outs.println("\t\tRow cache hit rate: " + rowCacheMBean.getRecentHitRate());
}
else

View File

@ -25,6 +25,7 @@ import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.io.util.BufferedRandomAccessFile;
@ -33,11 +34,11 @@ import org.apache.cassandra.service.StorageService;
import org.apache.commons.cli.*;
import org.apache.cassandra.config.ConfigurationException;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.io.sstable.*;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.Pair;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import static org.apache.cassandra.utils.ByteBufferUtil.bytesToHex;
import static org.apache.cassandra.utils.ByteBufferUtil.hexToBytes;
@ -47,12 +48,12 @@ import static org.apache.cassandra.utils.ByteBufferUtil.hexToBytes;
*/
public class SSTableExport
{
// size of the columns page
private static final int PAGE_SIZE = 1000;
private static ObjectMapper jsonMapper = new ObjectMapper();
private static final String KEY_OPTION = "k";
private static final String EXCLUDEKEY_OPTION = "x";
private static final String ENUMERATEKEYS_OPTION = "e";
private static Options options;
private static CommandLine cmd;
@ -72,42 +73,36 @@ public class SSTableExport
Option optEnumerate = new Option(ENUMERATEKEYS_OPTION, false, "enumerate keys only");
options.addOption(optEnumerate);
}
/**
* Wraps given string into quotes
* @param val string to quote
* @return quoted string
*/
private static String quote(String val)
{
return String.format("\"%s\"", val);
// disabling auto close of the stream
jsonMapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
}
/**
* JSON Hash Key serializer
* @param val value to set as a key
* @return JSON Hash key
*
* @param out The output steam to write data
* @param value value to set as a key
*/
private static String asKey(String val)
private static void writeKey(PrintStream out, String value)
{
return String.format("%s: ", quote(val));
writeJSON(out, value);
out.print(": ");
}
/**
* Serialize columns using given column iterator
*
* @param columns column iterator
* @param out output stream
* @param comparator columns comparator
* @param cfMetaData Column Family metadata (to get validator)
* @return pair of (number of columns serialized, last column serialized)
*/
private static void serializeColumns(Iterator<IColumn> columns, PrintStream out, AbstractType comparator, CFMetaData cfMetaData)
{
while (columns.hasNext())
{
IColumn column = columns.next();
serializeColumn(column, out, comparator, cfMetaData);
writeJSON(out, serializeColumn(columns.next(), comparator, cfMetaData));
if (columns.hasNext())
out.print(", ");
@ -116,47 +111,42 @@ public class SSTableExport
/**
* Serialize a given column to the JSON format
*
* @param column column presentation
* @param out output stream
* @param comparator columns comparator
* @param cfMetaData Column Family metadata (to get validator)
*
* @return column as serialized list
*/
private static void serializeColumn(IColumn column, PrintStream out, AbstractType comparator, CFMetaData cfMetaData)
private static List<Object> serializeColumn(IColumn column, AbstractType comparator, CFMetaData cfMetaData)
{
ArrayList<Object> serializedColumn = new ArrayList<Object>();
ByteBuffer name = ByteBufferUtil.clone(column.name());
ByteBuffer value = ByteBufferUtil.clone(column.value());
AbstractType validator = cfMetaData.getValueValidator(name);
out.print("[");
out.print(quote(comparator.getString(name)));
out.print(", ");
out.print(quote(validator.getString(value)));
out.print(", ");
out.print(column.timestamp());
serializedColumn.add(comparator.getString(name));
serializedColumn.add(validator.getString(value));
serializedColumn.add(column.timestamp());
if (column instanceof DeletedColumn)
{
out.print(", ");
out.print("\"d\"");
serializedColumn.add("d");
}
else if (column instanceof ExpiringColumn)
{
out.print(", ");
out.print("\"e\"");
out.print(", ");
out.print(((ExpiringColumn) column).getTimeToLive());
out.print(", ");
out.print(column.getLocalDeletionTime());
serializedColumn.add("e");
serializedColumn.add(((ExpiringColumn) column).getTimeToLive());
serializedColumn.add(column.getLocalDeletionTime());
}
else if (column instanceof CounterColumn)
{
out.print(", ");
out.print("\"c\"");
out.print(", ");
out.print(((CounterColumn) column).timestampOfLastDelete());
serializedColumn.add("c");
serializedColumn.add(((CounterColumn) column).timestampOfLastDelete());
}
out.print("]");
return serializedColumn;
}
/**
@ -172,7 +162,7 @@ public class SSTableExport
CFMetaData cfMetaData = columnFamily.metadata();
AbstractType comparator = columnFamily.getComparator();
out.print(asKey(bytesToHex(key.key)));
writeKey(out, bytesToHex(key.key));
out.print(isSuperCF ? "{" : "[");
if (isSuperCF)
@ -181,12 +171,12 @@ public class SSTableExport
{
IColumn column = row.next();
out.print(asKey(comparator.getString(column.name())));
writeKey(out, comparator.getString(column.name()));
out.print("{");
out.print(asKey("deletedAt"));
writeKey(out, "deletedAt");
out.print(column.getMarkedForDeleteAt());
out.print(", ");
out.print(asKey("subColumns"));
writeKey(out, "subColumns");
out.print("[");
serializeColumns(column.getSubColumns().iterator(), out, columnFamily.getSubComparator(), cfMetaData);
out.print("]");
@ -202,6 +192,7 @@ public class SSTableExport
}
out.print(isSuperCF ? "}" : "]");
}
/**
@ -417,4 +408,16 @@ public class SSTableExport
System.exit(0);
}
private static void writeJSON(PrintStream out, Object value)
{
try
{
jsonMapper.writeValue(out, value);
}
catch (Exception e)
{
throw new RuntimeException(e.getMessage(), e);
}
}
}

View File

@ -24,7 +24,6 @@ import sys, uuid, time
sys.path.append(join(abspath(dirname(__file__)), '../../drivers/py'))
import cql
from cql.connection import Connection
from __init__ import ThriftTester
from __init__ import thrift_client # TODO: temporary

View File

@ -113,6 +113,12 @@ public class SchemaLoader
standardCFMD(ks1, "Standard4"),
standardCFMD(ks1, "StandardLong1"),
standardCFMD(ks1, "StandardLong2"),
new CFMetaData(ks1,
"ValuesWithQuotes",
st,
BytesType.instance,
null)
.defaultValidator(UTF8Type.instance),
superCFMD(ks1, "Super1", LongType.instance),
superCFMD(ks1, "Super2", LongType.instance),
superCFMD(ks1, "Super3", LongType.instance),

View File

@ -1,4 +1,25 @@
package org.apache.cassandra.locator;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import static org.junit.Assert.assertEquals;

View File

@ -22,17 +22,15 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.CounterColumn;
import org.apache.cassandra.db.ExpiringColumn;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.io.sstable.SSTableWriter;
@ -243,4 +241,30 @@ public class SSTableExportTest extends SchemaLoader
assert ((String) colA.get(3)).equals("c");
assert (Long) colA.get(4) == Long.MIN_VALUE;
}
@Test
public void testEscapingDoubleQuotes() throws IOException
{
File tempSS = tempSSTableFile("Keyspace1", "ValuesWithQuotes");
ColumnFamily cfamily = ColumnFamily.create("Keyspace1", "ValuesWithQuotes");
SSTableWriter writer = new SSTableWriter(tempSS.getPath(), 2);
// Add rowA
cfamily.addColumn(null, new Column(ByteBufferUtil.bytes("data"), UTF8Type.instance.fromString("{\"foo\":\"bar\"}")));
writer.append(Util.dk("rowA"), cfamily);
cfamily.clear();
SSTableReader reader = writer.closeAndOpenReader();
// Export to JSON and verify
File tempJson = File.createTempFile("ValuesWithQuotes", ".json");
SSTableExport.export(reader, new PrintStream(tempJson.getPath()), new String[0]);
JSONObject json = (JSONObject) JSONValue.parse(new FileReader(tempJson));
JSONArray rowA = (JSONArray)json.get(asHex("rowA"));
JSONArray data = (JSONArray)rowA.get(0);
assert hexToBytes((String)data.get(0)).equals(ByteBufferUtil.bytes("data"));
assert data.get(1).equals("{\"foo\":\"bar\"}");
}
}