/* * @(#) RowMayExistQueryFilter.java * Created Dec 8, 2011 by oleg * (C) ONE, SIA */ package org.apache.cassandra.db.filter; import java.io.IOException; import java.util.Iterator; import org.apache.cassandra.db.ColumnFamily; import org.apache.cassandra.db.DecoratedKey; import org.apache.cassandra.db.IColumn; import org.apache.cassandra.db.IColumnContainer; import org.apache.cassandra.db.Memtable; import org.apache.cassandra.db.SuperColumn; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.io.SSTableReader; /** * This query checks for possible existance of several columns in a row. * * Only memtable and bloom filters are consulted. * * @author Oleg Anastasyev<oa@hq.one.lv> * */ public class ColumnsMayExistQueryFilter extends QueryFilter { private EmptyColumnIterator emptyColumnIterator ; private final Iterable<byte[]> names; private final ColumnCollector collector; private final int limit; private int collectedCount = 0; private DecoratedKey decoratedKey; /** * * @param key * @param path * @param names source of column names. Not all names could be fetched. * @param collector destination for may be found column names. * @param limit max number of columns to return */ public ColumnsMayExistQueryFilter(String key, QueryPath path, Iterable<byte[]> names, ColumnCollector collector, int limit) { super(key, path); this.names = names; this.collector = collector; this.limit = limit; } /* (non-Javadoc) * @see org.apache.cassandra.db.filter.QueryFilter#getMemColumnIterator(org.apache.cassandra.db.Memtable, org.apache.cassandra.db.ColumnFamily, org.apache.cassandra.db.marshal.AbstractType) */ @Override public ColumnIterator getMemColumnIterator(Memtable memtable, ColumnFamily cf, AbstractType comparator) { this.emptyColumnIterator = new EmptyColumnIterator(memtable.getTableName(), path.columnFamilyName); if (cf==null) return emptyColumnIterator; // row not found Iterator<byte[]> it = names.iterator(); while (collectedCount<limit && it.hasNext()) { byte[] name = it.next(); if (!collector.isCollected(name) && cf.getColumn(name)!=null) { collector.collect(name); collectedCount++; } } return emptyColumnIterator; } /* (non-Javadoc) * @see org.apache.cassandra.db.filter.QueryFilter#getSSTableColumnIterator(org.apache.cassandra.io.SSTableReader) */ @Override public ColumnIterator getSSTableColumnIterator(SSTableReader sstable) throws IOException { assert sstable.isColumnBloom() : "Only column families with column level bloom filters can use this query"; if (collectedCount>=limit) return emptyColumnIterator; // we already found all columns in memtable Iterator<byte[]> it = names.iterator(); while (collectedCount<limit && it.hasNext()) { byte[] name = it.next(); if (collector.isCollected(name)) continue; // did not found it previously. inspecting sstable bloom filter if (sstable.mayPresent(key, name)) { collector.collect(name); collectedCount++; } } return emptyColumnIterator; } /* (non-Javadoc) * @see org.apache.cassandra.db.filter.QueryFilter#collectReducedColumns(org.apache.cassandra.db.IColumnContainer, java.util.Iterator, int) */ @Override public void collectReducedColumns(IColumnContainer container, Iterator<IColumn> reducedColumns, int gcBefore) { } /* (non-Javadoc) * @see org.apache.cassandra.db.filter.QueryFilter#collectCollatedColumns(org.apache.cassandra.db.ColumnFamily, java.util.Iterator, int) */ @Override public void collectCollatedColumns(ColumnFamily returnCF, Iterator<IColumn> collatedColumns, int gcBefore) { } /* (non-Javadoc) * @see org.apache.cassandra.db.filter.QueryFilter#filterSuperColumn(org.apache.cassandra.db.SuperColumn, int) */ @Override public SuperColumn filterSuperColumn(SuperColumn superColumn, int gcBefore) { throw new UnsupportedOperationException( "Method FastRowMayExistQueryFilter.filterSuperColumn(superColumn, gcBefore) is not supported"); } public interface ColumnCollector { /** * Called by filter when column may exist in store, according to bloom filter * @param name */ void collect(byte[] name); /** * @return true, if column with name 'name' was previously collected by this filter * (this is neccessary for performance optimization) */ boolean isCollected(byte[] name); } }