use of org.apache.cassandra.thrift.IndexExpression in project eiger by wlloyd.
the class RangeSliceCommandSerializer method serialize.
public void serialize(RangeSliceCommand sliceCommand, DataOutput dos, int version) throws IOException {
dos.writeUTF(sliceCommand.keyspace);
dos.writeUTF(sliceCommand.column_family);
ByteBuffer sc = sliceCommand.super_column;
dos.writeInt(sc == null ? 0 : sc.remaining());
if (sc != null)
ByteBufferUtil.write(sc, dos);
TSerializer ser = new TSerializer(new TBinaryProtocol.Factory());
FBUtilities.serialize(ser, sliceCommand.predicate, dos);
if (version >= MessagingService.VERSION_11) {
if (sliceCommand.row_filter == null) {
dos.writeInt(0);
} else {
dos.writeInt(sliceCommand.row_filter.size());
for (IndexExpression expr : sliceCommand.row_filter) FBUtilities.serialize(ser, expr, dos);
}
}
AbstractBounds.serializer().serialize(sliceCommand.range, dos, version);
dos.writeInt(sliceCommand.maxResults);
if (version >= MessagingService.VERSION_11) {
dos.writeBoolean(sliceCommand.maxIsColumns);
}
}
use of org.apache.cassandra.thrift.IndexExpression in project eiger by wlloyd.
the class SecondaryIndexManager method getIndexSearchersForQuery.
/**
* Get a list of IndexSearchers from the union of expression index types
* @param clause the query clause
* @return the searchers needed to query the index
*/
private List<SecondaryIndexSearcher> getIndexSearchersForQuery(List<IndexExpression> clause) {
List<SecondaryIndexSearcher> indexSearchers = new ArrayList<SecondaryIndexSearcher>();
Map<String, Set<ByteBuffer>> groupByIndexType = new HashMap<String, Set<ByteBuffer>>();
//Group columns by type
for (IndexExpression ix : clause) {
SecondaryIndex index = getIndexForColumn(ix.column_name);
if (index == null)
continue;
Set<ByteBuffer> columns = groupByIndexType.get(index.getClass().getCanonicalName());
if (columns == null) {
columns = new HashSet<ByteBuffer>();
groupByIndexType.put(index.getClass().getCanonicalName(), columns);
}
columns.add(ix.column_name);
}
//create searcher per type
for (Map.Entry<String, Set<ByteBuffer>> entry : groupByIndexType.entrySet()) {
indexSearchers.add(getIndexForColumn(entry.getValue().iterator().next()).createSecondaryIndexSearcher(entry.getValue()));
}
return indexSearchers;
}
use of org.apache.cassandra.thrift.IndexExpression in project eiger by wlloyd.
the class KeysSearcher method getIndexedIterator.
public ColumnFamilyStore.AbstractScanIterator getIndexedIterator(final AbstractBounds<RowPosition> range, final ExtendedFilter filter) {
// Start with the most-restrictive indexed clause, then apply remaining clauses
// to each row matching that clause.
// TODO: allow merge join instead of just one index + loop
final IndexExpression primary = highestSelectivityPredicate(filter.getClause());
final SecondaryIndex index = indexManager.getIndexForColumn(primary.column_name);
if (logger.isDebugEnabled())
logger.debug("Primary scan clause is " + baseCfs.getComparator().getString(primary.column_name));
assert index != null;
final DecoratedKey indexKey = indexManager.getIndexKeyFor(primary.column_name, primary.value);
/*
* XXX: If the range requested is a token range, we'll have to start at the beginning (and stop at the end) of
* the indexed row unfortunately (which will be inefficient), because we have not way to intuit the small
* possible key having a given token. A fix would be to actually store the token along the key in the
* indexed row.
*/
final ByteBuffer startKey = range.left instanceof DecoratedKey ? ((DecoratedKey) range.left).key : ByteBufferUtil.EMPTY_BYTE_BUFFER;
final ByteBuffer endKey = range.right instanceof DecoratedKey ? ((DecoratedKey) range.right).key : ByteBufferUtil.EMPTY_BYTE_BUFFER;
return new ColumnFamilyStore.AbstractScanIterator() {
private ByteBuffer lastSeenKey = startKey;
private Iterator<IColumn> indexColumns;
private final QueryPath path = new QueryPath(baseCfs.columnFamily);
private int columnsRead = Integer.MAX_VALUE;
protected Row computeNext() {
int meanColumns = Math.max(index.getIndexCfs().getMeanColumns(), 1);
// We shouldn't fetch only 1 row as this provides buggy paging in case the first row doesn't satisfy all clauses
int rowsPerQuery = Math.max(Math.min(filter.maxRows(), filter.maxColumns() / meanColumns), 2);
while (true) {
if (indexColumns == null || !indexColumns.hasNext()) {
if (columnsRead < rowsPerQuery) {
logger.debug("Read only {} (< {}) last page through, must be done", columnsRead, rowsPerQuery);
return endOfData();
}
if (logger.isDebugEnabled())
logger.debug(String.format("Scanning index %s starting with %s", expressionString(primary), index.getBaseCfs().metadata.getKeyValidator().getString(startKey)));
QueryFilter indexFilter = QueryFilter.getSliceFilter(indexKey, new QueryPath(index.getIndexCfs().getColumnFamilyName()), lastSeenKey, endKey, false, rowsPerQuery);
ColumnFamily indexRow = index.getIndexCfs().getColumnFamily(indexFilter);
logger.debug("fetched {}", indexRow);
if (indexRow == null) {
logger.debug("no data, all done");
return endOfData();
}
Collection<IColumn> sortedColumns = indexRow.getSortedColumns();
columnsRead = sortedColumns.size();
indexColumns = sortedColumns.iterator();
IColumn firstColumn = sortedColumns.iterator().next();
// Paging is racy, so it is possible the first column of a page is not the last seen one.
if (lastSeenKey != startKey && lastSeenKey.equals(firstColumn.name())) {
// skip the row we already saw w/ the last page of results
indexColumns.next();
columnsRead--;
logger.debug("Skipping {}", baseCfs.getComparator().getString(firstColumn.name()));
} else if (range instanceof Range && indexColumns.hasNext() && firstColumn.equals(startKey)) {
// skip key excluded by range
indexColumns.next();
columnsRead--;
logger.debug("Skipping first key as range excludes it");
}
}
while (indexColumns.hasNext()) {
IColumn column = indexColumns.next();
lastSeenKey = column.name();
if (column.isMarkedForDelete()) {
logger.debug("skipping {}", column.name());
continue;
}
DecoratedKey dk = baseCfs.partitioner.decorateKey(lastSeenKey);
if (!range.right.isMinimum(baseCfs.partitioner) && range.right.compareTo(dk) < 0) {
logger.debug("Reached end of assigned scan range");
return endOfData();
}
if (!range.contains(dk)) {
logger.debug("Skipping entry {} outside of assigned scan range", dk.token);
continue;
}
logger.debug("Returning index hit for {}", dk);
ColumnFamily data = baseCfs.getColumnFamily(new QueryFilter(dk, path, filter.initialFilter()));
// While the column family we'll get in the end should contains the primary clause column, the initialFilter may not have found it and can thus be null
if (data == null)
data = ColumnFamily.create(baseCfs.metadata);
return new Row(dk, data);
}
}
}
public void close() throws IOException {
}
};
}
Aggregations