/*
* @(#) BloomFilterBuilder.java
* Created Jun 2, 2011 by oleg
* (C) ONE, SIA
*/
package org.apache.cassandra.io;
import java.io.IOException;
import java.util.SortedSet;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.DatabaseDescriptor.DiskAccessMode;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.io.util.BufferedRandomAccessFile;
import org.apache.cassandra.utils.BloomFilter;
import org.apache.log4j.Logger;
/**
* Unifies way of builder key-only and key+column bloom filters.
*
* @author Oleg Anastasyev<oa@hq.one.lv>
*
*/
public class BloomFilterWriter implements IColumnNameObserver
{
private static final Logger logger = Logger.getLogger(BloomFilterWriter.class);
public final static byte[] MARKEDFORDELETE = {'-','d','e','l'};
private final String filterFilename;
private final BloomFilter bf;
private final boolean bloomColumns;
private long keyCount;
private long estimatedElementCount;
/**
* @param columnCount
* @throws IOException
*
*/
public BloomFilterWriter(String filterFilename,long keyCount, long columnCount, boolean bloomColumns) throws IOException
{
this.filterFilename = filterFilename;
this.bloomColumns = bloomColumns;
this.estimatedElementCount = bloomColumns ? keyCount + columnCount : keyCount;
this.bf = BloomFilter.create(estimatedElementCount, 15);
}
/* (non-Javadoc)
* @see org.apache.cassandra.io.IColumnNameObserver#add(org.apache.cassandra.db.DecoratedKey, byte[])
*/
@Override
public void add(DecoratedKey<?> key, byte[] name)
{
bf.add(key.key,name);
}
@Override
public void add(DecoratedKey<?> key, ColumnFamily cf)
{
SortedSet<byte[]> columns = cf.getColumnNames();
for (byte[] bs : columns) {
bf.add(key.key,bs);
}
if (cf.isMarkedForDelete())
add(key,MARKEDFORDELETE);
}
public void add(DecoratedKey<?> key)
{
bf.add(key.key);
keyCount++;
}
/**
* @return the bloomColumns
*/
public boolean isBloomColumns()
{
return bloomColumns;
}
/**
* @return the bf
*/
public BloomFilter getFilter()
{
return bf;
}
/**
* Finishes bloom filter and flushes its data to disk.
*
* @return
* @throws IOException
*/
public BloomFilter build() throws IOException
{
// bloom filter
BufferedRandomAccessFile file = new BufferedRandomAccessFile(filterFilename, "rw", 128*1024);
file.setSkipCache(true);
BloomFilter.serializerForSSTable().serialize(bf, file);
file.close();
if (logger.isInfoEnabled())
logger.info("Written filter "+filterFilename+", with actual elements (estimated elements) counts: "+this.bf.getElementCount()+'('+estimatedElementCount+')' );
return bf;
}
}