You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2011/06/29 17:15:30 UTC
svn commit: r1141129 - in /cassandra/branches/cassandra-0.7: CHANGES.txt
src/java/org/apache/cassandra/db/ColumnFamilyStore.java
Author: slebresne
Date: Wed Jun 29 15:15:29 2011
New Revision: 1141129
URL: http://svn.apache.org/viewvc?rev=1141129&view=rev
Log:
Fix scan wrongly throwing assertion errors
patch by slebresne; reviewed by jbellis for CASSANDRA-2653
Modified:
cassandra/branches/cassandra-0.7/CHANGES.txt
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
Modified: cassandra/branches/cassandra-0.7/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/CHANGES.txt?rev=1141129&r1=1141128&r2=1141129&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.7/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.7/CHANGES.txt Wed Jun 29 15:15:29 2011
@@ -26,6 +26,7 @@
* fix race that could result in Hadoop writer failing to throw an
exception encountered after close() (CASSANDRA-2755)
* fix CLI parsing of read_repair_chance (CASSANDRA-2837)
+ * fix scan wrongly throwing assertion error (CASSANDRA-2653)
0.7.6
Modified: cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/ColumnFamilyStore.java?rev=1141129&r1=1141128&r2=1141129&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/ColumnFamilyStore.java (original)
+++ cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/db/ColumnFamilyStore.java Wed Jun 29 15:15:29 2011
@@ -1486,6 +1486,16 @@ public class ColumnFamilyStore implement
return rows;
}
+ private NamesQueryFilter getExtraFilter(IndexClause clause)
+ {
+ SortedSet<ByteBuffer> columns = new TreeSet<ByteBuffer>(getComparator());
+ for (IndexExpression expr : clause.expressions)
+ {
+ columns.add(expr.column_name);
+ }
+ return new NamesQueryFilter(columns);
+ }
+
public List<Row> scan(IndexClause clause, AbstractBounds range, IFilter dataFilter)
{
// Start with the most-restrictive indexed clause, then apply remaining clauses
@@ -1502,50 +1512,33 @@ public class ColumnFamilyStore implement
// it needs to be expanded to include those too
IFilter firstFilter = dataFilter;
NamesQueryFilter extraFilter = null;
- if (clause.expressions.size() > 1)
+ if (dataFilter instanceof SliceQueryFilter)
{
- if (dataFilter instanceof SliceQueryFilter)
+ // if we have a high chance of getting all the columns in a single index slice, do that.
+ // otherwise, we'll create an extraFilter (lazily) to fetch by name the columns referenced by the additional expressions.
+ if (getMaxRowSize() < DatabaseDescriptor.getColumnIndexSize())
{
- // if we have a high chance of getting all the columns in a single index slice, do that.
- // otherwise, create an extraFilter to fetch by name the columns referenced by the additional expressions.
- if (getMaxRowSize() < DatabaseDescriptor.getColumnIndexSize())
- {
- logger.debug("Expanding slice filter to entire row to cover additional expressions");
- firstFilter = new SliceQueryFilter(ByteBufferUtil.EMPTY_BYTE_BUFFER,
- ByteBufferUtil.EMPTY_BYTE_BUFFER,
- ((SliceQueryFilter) dataFilter).reversed,
- Integer.MAX_VALUE);
- }
- else
- {
- logger.debug("adding extraFilter to cover additional expressions");
- SortedSet<ByteBuffer> columns = new TreeSet<ByteBuffer>(getComparator());
- for (IndexExpression expr : clause.expressions)
- {
- if (expr == primary)
- continue;
- columns.add(expr.column_name);
- }
- extraFilter = new NamesQueryFilter(columns);
- }
+ logger.debug("Expanding slice filter to entire row to cover additional expressions");
+ firstFilter = new SliceQueryFilter(ByteBufferUtil.EMPTY_BYTE_BUFFER,
+ ByteBufferUtil.EMPTY_BYTE_BUFFER,
+ ((SliceQueryFilter) dataFilter).reversed,
+ Integer.MAX_VALUE);
}
- else
+ }
+ else
+ {
+ logger.debug("adding columns to firstFilter to cover additional expressions");
+ // just add in columns that are not part of the resultset
+ assert dataFilter instanceof NamesQueryFilter;
+ SortedSet<ByteBuffer> columns = new TreeSet<ByteBuffer>(getComparator());
+ for (IndexExpression expr : clause.expressions)
{
- logger.debug("adding columns to firstFilter to cover additional expressions");
- // just add in columns that are not part of the resultset
- assert dataFilter instanceof NamesQueryFilter;
- SortedSet<ByteBuffer> columns = new TreeSet<ByteBuffer>(getComparator());
- for (IndexExpression expr : clause.expressions)
- {
- if (expr == primary || ((NamesQueryFilter) dataFilter).columns.contains(expr.column_name))
- continue;
- columns.add(expr.column_name);
- }
- if (columns.size() > 0)
- {
- columns.addAll(((NamesQueryFilter) dataFilter).columns);
- firstFilter = new NamesQueryFilter(columns);
- }
+ columns.add(expr.column_name);
+ }
+ if (columns.size() > 0)
+ {
+ columns.addAll(((NamesQueryFilter) dataFilter).columns);
+ firstFilter = new NamesQueryFilter(columns);
}
}
@@ -1600,18 +1593,23 @@ public class ColumnFamilyStore implement
// get the row columns requested, and additional columns for the expressions if necessary
ColumnFamily data = getColumnFamily(new QueryFilter(dk, path, firstFilter));
- assert data != null : String.format("No data found for %s in %s:%s (original filter %s) from expression %s",
- firstFilter, dk, path, dataFilter, expressionString(primary));
+ // While we the column family we'll get in the end should contains the primary clause column, the firstFilter may not have found it.
+ if (data == null)
+ data = ColumnFamily.create(metadata);
logger.debug("fetched data row {}", data);
- if (extraFilter != null)
+ if (dataFilter instanceof SliceQueryFilter)
{
// we might have gotten the expression columns in with the main data slice, but
// we can't know for sure until that slice is done. So, we'll do the extra query
// if we go through and any expression columns are not present.
for (IndexExpression expr : clause.expressions)
{
- if (expr != primary && data.getColumn(expr.column_name) == null)
+ if (data.getColumn(expr.column_name) == null)
{
+ logger.debug("adding extraFilter to cover additional expressions");
+ // Lazily creating extra filter
+ if (extraFilter == null)
+ extraFilter = getExtraFilter(clause);
data.addAll(getColumnFamily(new QueryFilter(dk, path, extraFilter)));
break;
}
@@ -1675,11 +1673,10 @@ public class ColumnFamilyStore implement
private static boolean satisfies(ColumnFamily data, IndexClause clause, IndexExpression first)
{
+ // We enforces even the primary clause because reads are not synchronized with writes and it is thus possible to have a race
+ // where the index returned a row which doesn't have the primarycolumn when we actually read it
for (IndexExpression expression : clause.expressions)
{
- // (we can skip "first" since we already know it's satisfied)
- if (expression == first)
- continue;
// check column data vs expression
IColumn column = data.getColumn(expression.column_name);
if (column == null)