package me.xhh.hector06;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import me.prettyprint.cassandra.dao.Command;
import me.prettyprint.cassandra.service.KeyspaceService;
import me.prettyprint.hector.api.exceptions.HNotFoundException;
import me.prettyprint.hector.api.exceptions.HectorException;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ColumnPath;
import org.apache.cassandra.thrift.KeyRange;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.thrift.SliceRange;
import org.apache.cassandra.thrift.SuperColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Database Accessor for accessing the Cassandra database.
*/
public class DBA {
private static final Logger log = LoggerFactory.getLogger(DBA.class);
/**
* Interface for all Column Families. Note: please use enum as type of a Column Family and let it implement this interface (enum
* constants' toString() must have the same names as the real (super) Column Families).
*/
public static interface ColumnFamily {
String toString();
}
/**
* Interface for all Column names. Note: please use enum as type of a Column name and let it implement this interface (enum
* constants' toString() must have the same names as the real column names).
*/
public static interface ColumnName {
String toString();
}
/**
* @param <T>
* type column name, must be String or Long
*/
public static class ColumnMap<T> implements Serializable {
private static final long serialVersionUID = 6461999789967087137L;
private Map<T, String> data;
public ColumnMap(int initialCapacity) {
this.data = new LinkedHashMap<T, String>(initialCapacity);
}
public ColumnMap(Map<T, String> data) {
this.data = data;
}
/**
* Use this when T is String
*
* @param colName
* @return
*/
public String get(ColumnName colName) {
return data.get(colName.toString());
}
/**
* Use this when T is String
*
* @param colName
* @return
*/
public String get(String colName) {
return data.get(colName);
}
/**
* Use this when T is Long
*
* @param colName
* @return
*/
public String get(Long colName) {
return data.get(colName);
}
public int size() {
return data.size();
}
/**
* Use this when T is String
*
* @param colName
*/
public boolean containsKey(ColumnName colNmae) {
return data.containsKey(colNmae.toString());
}
/**
* Use this when T is Long
*
* @param colName
*/
public boolean containsKey(Long colNmae) {
return data.containsKey(colNmae);
}
/**
* @return
*/
public boolean isEmpty() {
return data.isEmpty();
}
public Set<T> keySet() {
return data.keySet();
}
}
private DBConfig dbConfig;
public DBA() {
}
public DBA(DBConfig dbConfig) {
this.dbConfig = dbConfig;
}
public void insertValue(ColumnFamily colFamily, String key, Object colName, String colValue) throws HectorException {
insertValue(colFamily, key, null, colName, colValue);
}
public void insertValue(final ColumnFamily colFamily, final String key, final Object superColName, final Object colName,
final String colValue) throws HectorException {
execute(new Command<Void>() {
@Override
public Void execute(KeyspaceService ks) throws HectorException {
ks.insert(key, createColumnPath(colFamily, superColName, colName), DBUtil.bytes(colValue));
return null;
}
});
}
public void insertColumnsOrSuperColumns(final ColumnFamily colFamily, final String key, final List<Column> cols,
final List<SuperColumn> superCols) throws HectorException { // TODO batch
/*
* Map<String, List<Column>> colMap = new HashMap<String, List<Column>>(1); Map<String, List<SuperColumn>> superColMap = new
* HashMap<String, List<SuperColumn>>(1); if (cols != null) colMap.put(colFamily.toString(), cols); if (superCols != null)
* superColMap.put(colFamily.toString(), superCols); insertColumns(key, colMap, superColMap);
*/
/*
* BatchMutation bm = new BatchMutation(); List<String> colFamilyList = new ArrayList<String>(1);
* colFamilyList.add(colFamily.toString()); if (cols != null) { for (Column c : cols) bm.addInsertion(key, colFamilyList, c); }
* if (superCols != null) { for (SuperColumn sc : superCols) bm.addSuperInsertion(key, colFamilyList, sc); } batchMutate(bm);
*/
execute(new Command<Void>() {
public Void execute(KeyspaceService ks) throws HectorException {
if (cols != null) {
for (Column c : cols)
ks.insert(key, createColumnPath(colFamily, null, c.getName()), c.getValue());
}
if (superCols != null) {
for (SuperColumn sc : superCols) {
for (Column c : sc.getColumns())
ks.insert(key, createColumnPath(colFamily, sc.getName(), c.getName()), c.getValue());
}
}
return null;
}
});
}
public void insertColumns(ColumnFamily colFamily, String key, List<Column> cols) throws HectorException {
if (cols == null || cols.isEmpty())
throw new IllegalArgumentException("Columns can not be null or empty!");
else
insertColumnsOrSuperColumns(colFamily, key, cols, null);
}
public void insertColumns(ColumnFamily colFamily, String key, Object superColName, List<Column> columns) throws HectorException {
SuperColumn superCol = DBUtil.createSuperColumn(superColName, columns);
insertSuperColumn(colFamily, key, superCol);
}
public void insertSuperColumn(ColumnFamily colFamily, String key, SuperColumn superCol) throws HectorException {
if (superCol == null)
throw new IllegalArgumentException("Super column can not be null!");
else
insertColumnsOrSuperColumns(colFamily, key, null, Arrays.asList(superCol));
}
/*
* public void insertColumns(final String key, final Map<String, List<Column>> colMap, final Map<String, List<SuperColumn>>
* superColMap) throws HectorException { execute(new Command<Void>() { // TODO batch public Void execute(KeyspaceService ks) throws
* HectorException { ks.batchInsert(key, colMap, superColMap); return null; } }); } public void batchMutate(final Map<String,
* Map<String, List<Mutation>>> mutationMap) throws HectorException { execute(new Command<Void>() { // TODO batch public Void
* execute(KeyspaceService ks) throws HectorException { ks.batchMutate(mutationMap); return null; } }); } public void
* batchMutate(final BatchMutation batchMutation) throws HectorException { execute(new Command<Void>() { public Void
* execute(KeyspaceService ks) throws HectorException { ks.batchMutate(batchMutation); return null; } }); }
*/
public String getValue(final ColumnFamily colFamily, final String key, final Object colName) throws HectorException {
return getValue(colFamily, key, null, colName);
}
/**
* @return The string value; null if no value exists for the given key.
*/
public String getValue(final ColumnFamily colFamily, final String key, final Object superColName, final Object colName)
throws HectorException {
return execute(new Command<String>() {
public String execute(KeyspaceService ks) throws HectorException {
try {
return DBUtil.string(ks.getColumn(key, createColumnPath(colFamily, superColName, colName)).getValue());
} catch (HNotFoundException e) {
return null;
}
}
});
}
public boolean columnExists(ColumnFamily colFamily, String key, Object colName) throws HectorException {
return columnExists(colFamily, key, null, colName);
}
public boolean columnExists(final ColumnFamily colFamily, final String key, final Object superColName, final Object colName)
throws HectorException {
return execute(new Command<Boolean>() {
public Boolean execute(KeyspaceService ks) throws HectorException {
try {
return ks.getColumn(key, createColumnPath(colFamily, superColName, colName)) != null;
} catch (HNotFoundException e) {
return false;
}
}
});
}
public Column getFirstColumn(ColumnFamily colFamily, String key) throws HectorException {
return getFirstColumn(colFamily, key, null);
}
public Column getFirstColumn(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
List<Column> columns = getColumns(colFamily, key, superColName, null, null, null, 1, false);
return columns.isEmpty() ? null : columns.get(0);
}
public byte[] getFirstColumnName(ColumnFamily colFamily, String key) throws HectorException {
return getFirstColumnName(colFamily, key, null);
}
public byte[] getFirstColumnName(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
Column c = getFirstColumn(colFamily, key, superColName);
return c == null ? null : c.getName();
}
public String getFirstValue(ColumnFamily colFamily, String key) throws HectorException {
return getFirstValue(colFamily, key, null);
}
public String getFirstValue(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
Column c = getFirstColumn(colFamily, key, superColName);
return c == null ? null : DBUtil.string(c.getValue());
}
public Column getLastColumn(ColumnFamily colFamily, String key) throws HectorException {
return getLastColumn(colFamily, key, null);
}
public Column getLastColumn(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
List<Column> columns = getColumns(colFamily, key, superColName, null, null, null, 1, true);
return columns.isEmpty() ? null : columns.get(0);
}
public byte[] getLastColumnName(ColumnFamily colFamily, String key) throws HectorException {
return getLastColumnName(colFamily, key, null);
}
public byte[] getLastColumnName(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
Column c = getLastColumn(colFamily, key, superColName);
return c == null ? null : c.getName();
}
public String getLastValue(ColumnFamily colFamily, String key) throws HectorException {
return getLastValue(colFamily, key, null);
}
public String getLastValue(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
Column c = getLastColumn(colFamily, key, superColName);
return c == null ? null : DBUtil.string(c.getValue());
}
/**
* Read all columns of the column family. This does NOT applies to super column families.<br/>
* Note: reading all columns could be slow.
*
* @param colFamily
* the column family, can NOT be super column family
* @param key
* @return
* @throws HectorException
*/
public List<Column> getAllColumns(ColumnFamily colFamily, String key) throws HectorException {
return getAllColumns(colFamily, key, null, false);
}
public List<Column> getAllColumns(final ColumnFamily colFamily, final String key, final Object superColName)
throws HectorException {
return getAllColumns(colFamily, key, superColName, false);
}
/**
* Read all columns by reading 1000 columns at a time.
*
* @param colFamily
* @param key
* @param superColName
* @param reversed
* @return
*/
public List<Column> getAllColumns(final ColumnFamily colFamily, final String key, final Object superColName, final boolean reversed)
throws HectorException {
return getAllColumns(colFamily, key, superColName, 1000, reversed);
}
/**
* Read all columns of the column family.<br/>
* Note: reading all columns could be slow.
*
* @param colFamily
* the (super) column family
* @param key
* @param superColName
* the super column name when reading all columns from a super column family
* @param count
* how many columns to read at a time
* @return
*/
public List<Column> getAllColumns(final ColumnFamily colFamily, final String key, final Object superColName, final int count,
final boolean reversed) {
if (count <= 1)
throw new IllegalArgumentException("count must be bigger than 1!");
return execute(new Command<List<Column>>() {
public List<Column> execute(KeyspaceService ks) throws HectorException {
return _getAllColumns(colFamily, key, superColName, count, reversed, ks);
}
});
}
private List<Column> _getAllColumns(final ColumnFamily colFamily, final String key, final Object superColName,
final boolean reversed, final KeyspaceService ks) {
return _getAllColumns(colFamily, key, superColName, 1000, reversed, ks);
}
/**
* @param colFamily
* @param key
* @param superColName
* @param count
* @param reversed
* @param ks
* @return
*/
private List<Column> _getAllColumns(final ColumnFamily colFamily, final String key, final Object superColName, final int count,
final boolean reversed, final KeyspaceService ks) {
ColumnParent cp = new ColumnParent(colFamily.toString());
if (superColName != null)
cp.setSuper_column(DBUtil.bytesForName(superColName));
SlicePredicate predicate = new SlicePredicate();
SliceRange range = new SliceRange();
range.setStart(new byte[0]);
range.setFinish(new byte[0]);
range.setCount(count);
range.setReversed(reversed);
predicate.setSlice_range(range);
List<Column> all = new ArrayList<Column>();
do {
List<Column> data = ks.getSlice(key, cp, predicate);
int size = data.size();
if (size < count) { // end reached
all.addAll(data);
break;
} else { // continue to read more
range.setStart(data.remove(size - 1).getName());
all.addAll(data);
}
} while (true);
return all;
}
public List<Column> getColumns(ColumnFamily colFamily, String key, Object superColName, List<ColumnName> colNames)
throws HectorException {
return getColumns(colFamily, key, superColName, colNames, null, null, 0, false);
}
public List<Column> getColumnsTypeLong(ColumnFamily colFamily, String key, Object superColName, List<Long> colNames)
throws HectorException {
return getColumnsTypeLong(colFamily, key, superColName, colNames, null, null, 0, false);
}
public List<Column> getColumns(ColumnFamily colFamily, String key, byte[] start, int count) throws HectorException {
return getColumns(colFamily, key, null, null, start, null, count, false);
}
public List<Column> getColumnsTypeLong(ColumnFamily colFamily, String key, byte[] start, int count) throws HectorException {
return getColumnsTypeLong(colFamily, key, null, null, start, null, count, false);
}
public List<Column> getColumns(ColumnFamily colFamily, String key, byte[] start, int count, boolean reversed)
throws HectorException {
return getColumns(colFamily, key, null, null, start, null, count, reversed);
}
public List<Column> getColumnsTypeLong(ColumnFamily colFamily, String key, byte[] start, int count, boolean reversed)
throws HectorException {
return getColumnsTypeLong(colFamily, key, null, null, start, null, count, reversed);
}
public List<Column> getColumns(ColumnFamily colFamily, String key, Object superColName, byte[] start, int count)
throws HectorException {
return getColumns(colFamily, key, superColName, null, start, null, count, false);
}
public List<Column> getColumnsTypeLong(ColumnFamily colFamily, String key, Object superColName, byte[] start, int count)
throws HectorException {
return getColumnsTypeLong(colFamily, key, superColName, null, start, null, count, false);
}
public List<Column> getColumns(final ColumnFamily colFamily, final String key, final Object superColName,
final List<ColumnName> colNames, final byte[] start, final byte[] finish, final int count, final boolean reversed)
throws HectorException {
return execute(new Command<List<Column>>() {
public List<Column> execute(KeyspaceService ks) throws HectorException {
SlicePredicate predicate = new SlicePredicate();
if (colNames != null) {
for (ColumnName cn : colNames) {
if (cn != null)
predicate.addToColumn_names(DBUtil.bytes(cn.toString()));
}
} else {
SliceRange range = new SliceRange();
range.setStart(start == null ? new byte[0] : start);
range.setFinish(finish == null ? new byte[0] : finish);
if (count > 0)
range.setCount(count);
range.setReversed(reversed);
predicate.setSlice_range(range);
}
ColumnParent cp = new ColumnParent(colFamily.toString());
if (superColName != null)
cp.setSuper_column(DBUtil.bytesForName(superColName));
return ks.getSlice(key, cp, predicate);
}
});
}
public List<Column> getColumnsTypeLong(final ColumnFamily colFamily, final String key, final Object superColName,
final List<Long> colNames, final byte[] start, final byte[] finish, final int count, final boolean reversed)
throws HectorException {
return execute(new Command<List<Column>>() {
public List<Column> execute(KeyspaceService ks) throws HectorException {
SlicePredicate predicate = new SlicePredicate();
if (colNames != null) {
for (Long cn : colNames) {
if (cn != null)
predicate.addToColumn_names(DBUtil.bytesFromLong(cn));
}
} else {
SliceRange range = new SliceRange();
range.setStart(start == null ? new byte[0] : start);
range.setFinish(finish == null ? new byte[0] : finish);
if (count > 0)
range.setCount(count);
range.setReversed(reversed);
predicate.setSlice_range(range);
}
ColumnParent cp = new ColumnParent(colFamily.toString());
if (superColName != null)
cp.setSuper_column(DBUtil.bytesForName(superColName));
return ks.getSlice(key, cp, predicate);
}
});
}
public ColumnMap<String> getAllColumnsToMap(ColumnFamily colFamily, String key) throws HectorException {
return getAllColumnsToMap(colFamily, key, null);
}
public ColumnMap<String> getAllColumnsToMap(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
return DBUtil.columnsToMap(getAllColumns(colFamily, key, superColName));
}
public ColumnMap<String> getColumnsToMap(ColumnFamily colFamily, String key, Object superColName, List<ColumnName> colNames)
throws HectorException {
return DBUtil.columnsToMap(getColumns(colFamily, key, superColName, colNames, null, null, 0, false));
}
public ColumnMap<String> getColumnsToMap(ColumnFamily colFamily, String key, Object superColName, ColumnName... colNames)
throws HectorException {
return DBUtil.columnsToMap(getColumns(colFamily, key, superColName, Arrays.asList(colNames), null, null, 0, false));
}
public ColumnMap<Long> getColumnsToMapTypeLong(ColumnFamily colFamily, String key, Object superColName, List<Long> colNames)
throws HectorException {
return DBUtil.columnsToMapTypeLong(getColumnsTypeLong(colFamily, key, superColName, colNames, null, null, 0, false));
}
public ColumnMap<Long> getColumnsToMapTypeLong(ColumnFamily colFamily, String key, Object superColName, Object... colNames)
throws HectorException {
return getColumnsToMapTypeLong(colFamily, key, superColName, Arrays.asList(colNames));
}
public int getCount(ColumnFamily colFamily, String key) throws HectorException {
return getCount(colFamily, key, null);
}
public int getCount(final ColumnFamily colFamily, final String key, final Object superColName) throws HectorException {
if (key == null)
throw new IllegalArgumentException("key can not be null!");
return execute(new Command<Integer>() {
public Integer execute(KeyspaceService ks) throws HectorException {
ColumnParent cp = new ColumnParent(colFamily.toString());
if (superColName != null)
cp.setSuper_column(DBUtil.bytesForName(superColName));
return ks.getCount(key, cp);
}
});
}
public SuperColumn getSuperColumn(final ColumnFamily colFamily, final String key, final Object superColName)
throws HectorException {
if (superColName == null)
throw new IllegalArgumentException("super column name can not be null!");
return execute(new Command<SuperColumn>() {
public SuperColumn execute(KeyspaceService ks) throws HectorException {
try {
SuperColumn sc = ks.getSuperColumn(key, createColumnPath(colFamily, superColName, null));
// Note: treat empty SuperColumn as nonexistent
if (sc == null || !sc.getColumnsIterator().hasNext())
return null;
else
return sc;
} catch (HNotFoundException e) {
return null;
}
}
});
}
/**
* @param size
* Note: can NOT be smaller than 1
*/
public SuperColumn getSuperColumn(final ColumnFamily colFamily, final String key, final Object superColName,
final boolean reversed, final int size) throws HectorException {
if (superColName == null)
throw new IllegalArgumentException("super column name can not be null!");
return execute(new Command<SuperColumn>() {
public SuperColumn execute(KeyspaceService ks) throws HectorException {
if (size < 1)
throw new IllegalArgumentException("getSuperColumn: size can NOT be small than 1!");
try {
SuperColumn sc = ks.getSuperColumn(key, createColumnPath(colFamily, superColName, null), reversed, size);
// Note: treat empty SuperColumn as nonexistent
if (sc == null || !sc.getColumnsIterator().hasNext())
return null;
else
return sc;
} catch (HNotFoundException e) {
return null;
}
}
});
}
public boolean superColumnExists(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
return getSuperColumn(colFamily, key, superColName, false, 1) != null;
}
/**
* Call {@link #getAllSuperColumns(ColumnFamily, String, int, boolean)}<br/>
* with count: 100, reversed: false.
*
* @param colFamily
* @param key
* @return
* @throws HectorException
*/
public List<SuperColumn> getAllSuperColumns(ColumnFamily colFamily, String key) throws HectorException {
return getAllSuperColumns(colFamily, key, 100, false);
}
/**
* @param colFamily
* @param key
* @param reversed
* @return
* @throws HectorException
* @see {@link #getAllSuperColumns(ColumnFamily, String, int, boolean)}
*/
public List<SuperColumn> getAllSuperColumns(ColumnFamily colFamily, String key, boolean reversed) throws HectorException {
return getAllSuperColumns(colFamily, key, 100, reversed);
}
/**
* Read all super columns (together with all columns of each super column).<br/>
* Note: reading all super columns might be slow.
*
* @param colFamily
* @param key
* @param count
* @param reversed
* @return
* @throws HectorException
*/
public List<SuperColumn> getAllSuperColumns(final ColumnFamily colFamily, final String key, final int count, final boolean reversed)
throws HectorException {
if (count <= 1)
throw new IllegalArgumentException("count must be bigger than 1!");
return execute(new Command<List<SuperColumn>>() {
public List<SuperColumn> execute(KeyspaceService ks) throws HectorException {
ColumnParent cp = new ColumnParent(colFamily.toString());
SlicePredicate predicate = new SlicePredicate();
SliceRange range = new SliceRange();
range.setStart(new byte[0]);
range.setFinish(new byte[0]);
range.setCount(count);
range.setReversed(reversed);
predicate.setSlice_range(range);
List<SuperColumn> all = new ArrayList<SuperColumn>();
do {
List<SuperColumn> data = ks.getSuperSlice(key, cp, predicate);
int size = data.size();
if (size < count) { // end reached
all.addAll(data);
break;
} else { // continue to read more
range.setStart(data.remove(size - 1).getName());
all.addAll(data);
}
} while (true);
return all;
}
});
}
public List<SuperColumn> getSuperColumns(final ColumnFamily colFamily, final String key, final Object start, final int count)
throws HectorException {
return getSuperColumns(colFamily, key, null, start, null, count, false);
}
public List<SuperColumn> getSuperColumns(final ColumnFamily colFamily, final String key, final Object start, final int count,
final boolean reversed) throws HectorException {
return getSuperColumns(colFamily, key, null, start, null, count, reversed);
}
public List<SuperColumn> getSuperColumns(ColumnFamily colFamily, String key, byte[] start, byte[] finish, int count)
throws HectorException {
return getSuperColumns(colFamily, key, null, start, finish, count, false);
}
public List<SuperColumn> getSuperColumns(final ColumnFamily colFamily, final String key, final List<Object> superColNames)
throws HectorException {
return getSuperColumns(colFamily, key, superColNames, null, null, 0, false);
}
public List<SuperColumn> getSuperColumns(final ColumnFamily colFamily, final String key, final List<Object> superColNames,
final Object start, final Object finish, final int count, final boolean reversed) throws HectorException {
return execute(new Command<List<SuperColumn>>() {
public List<SuperColumn> execute(KeyspaceService ks) throws HectorException {
SlicePredicate predicate = new SlicePredicate();
if (superColNames != null) {
for (Object scn : superColNames)
predicate.addToColumn_names(DBUtil.bytesForName(scn));
} else {
SliceRange range = new SliceRange();
range.setStart(DBUtil.bytesForName(start == null ? "" : start));
range.setFinish(DBUtil.bytesForName(finish == null ? "" : finish));
if (count > 0)
range.setCount(count);
range.setReversed(reversed);
predicate.setSlice_range(range);
}
List<SuperColumn> result = ks.getSuperSlice(key, new ColumnParent(colFamily.toString()), predicate);
/*
* TODO Bug here! To reproduce: Insert 10 super columns for a key, then delete 3 super columns, then delete all keys,
* then insert again the old 10 super columns, then getSuperColumn() with start=null,finish=null,count=5, then you get
* 8 super columns! If the "delete 3 super columns... insert again..." things were not done, there is no problem. Also,
* if count is 1 there is no problem (only one super column is returned).
*/
if (count > 1 && result.size() > count)
return result.subList(0, count);
else
return result;
}
});
}
public SuperColumn getFirstSuperColumn(ColumnFamily colFamily, String key) throws HectorException {
List<SuperColumn> superColumns = getSuperColumns(colFamily, key, null, null, null, 1, false);
return superColumns.isEmpty() ? null : superColumns.get(0);
}
public byte[] getFirstSuperColumnName(ColumnFamily colFamily, String key) throws HectorException {
SuperColumn sc = getFirstSuperColumn(colFamily, key);
return sc == null ? null : sc.getName();
}
public SuperColumn getLastSuperColumn(ColumnFamily colFamily, String key) throws HectorException {
List<SuperColumn> superColumns = getSuperColumns(colFamily, key, null, null, null, 1, true);
return superColumns.isEmpty() ? null : superColumns.get(0);
}
public byte[] getLastSuperColumnName(ColumnFamily colFamily, String key) throws HectorException {
SuperColumn sc = getLastSuperColumn(colFamily, key);
return sc == null ? null : sc.getName();
}
public List<String> getKeys(ColumnFamily colFamily, String start, int count) throws HectorException {
return getKeys(colFamily, start, null, count);
}
public List<String> getKeys(ColumnFamily colFamily, String start, String end, int count) throws HectorException {
Map<String, List<Column>> map = getKeysAndColumns(colFamily, start, end, count, null, null, null, null, 1, false);
return new ArrayList<String>(map.keySet());
}
public Map<String, List<Column>> getKeysAndColumns(ColumnFamily colFamily, String start, String end, int count,
Object superColName, List<Object> colNames) throws HectorException {
if (colNames == null || colNames.isEmpty())
throw new IllegalArgumentException("getKeysAndColumns: you must specify the Column names!");
return getKeysAndColumns(colFamily, start, end, count, superColName, colNames, null, null, 0, false);
}
/**
* @return true is returned is the key doesn't exist or is empty (i.e. has no columns or super columns)
*/
public boolean isKeyEmpty(ColumnFamily colFamily, String key) throws HectorException {
return getColumns(colFamily, key, null, 1).isEmpty();
}
/**
* @param colFamily
* @param superColName
* @return
* @throws HectorException
* @see {@link #getAllKeysAndColumns(ColumnFamily, Object, boolean)}
*/
public Map<String, List<Column>> getAllKeysAndColumns(final ColumnFamily colFamily, final Object superColName)
throws HectorException {
return getAllKeysAndColumns(colFamily, superColName, false);
}
/**
* Read all keys and all columns of each key or the super column of each key (if the given super column name is not null).
*
* @param colFamily
* @param superColName
* super column name, should be null for normal column family (not super)
* @param colReversed
* whether to load columns reversely for each key
* @return key: key, value: columns
*/
public Map<String, List<Column>> getAllKeysAndColumns(final ColumnFamily colFamily, final Object superColName,
final boolean colReversed) throws HectorException {
return execute(new Command<Map<String, List<Column>>>() {
public Map<String, List<Column>> execute(KeyspaceService ks) throws HectorException {
List<String> allKeys = _getAllKeys(colFamily, ks);
if (allKeys.isEmpty())
return new HashMap<String, List<Column>>(0);
LinkedHashMap<String, List<Column>> results = new LinkedHashMap<String, List<Column>>(allKeys.size());
for (String key : allKeys)
results.put(key, _getAllColumns(colFamily, key, superColName, colReversed, ks));
return results;
}
});
}
public Map<String, List<Column>> getAllKeysAndColumns(final ColumnFamily colFamily, final Object superColName,
final List<ColumnName> colNames) throws HectorException {
return execute(new Command<Map<String, List<Column>>>() {
public Map<String, List<Column>> execute(KeyspaceService ks) throws HectorException {
List<String> allKeys = _getAllKeys(colFamily, ks);
if (allKeys.isEmpty())
return new HashMap<String, List<Column>>(0);
LinkedHashMap<String, List<Column>> results = new LinkedHashMap<String, List<Column>>(allKeys.size());
for (String key : allKeys)
results.put(key, getColumns(colFamily, key, superColName, colNames));
return results;
}
});
}
public Map<String, List<Column>> getAllKeysAndColumnsTypeLong(final ColumnFamily colFamily, final Object superColName,
final List<Long> colNames) throws HectorException {
return execute(new Command<Map<String, List<Column>>>() {
public Map<String, List<Column>> execute(KeyspaceService ks) throws HectorException {
List<String> allKeys = _getAllKeys(colFamily, ks);
if (allKeys.isEmpty())
return new HashMap<String, List<Column>>(0);
LinkedHashMap<String, List<Column>> results = new LinkedHashMap<String, List<Column>>(allKeys.size());
for (String key : allKeys)
results.put(key, getColumnsTypeLong(colFamily, key, superColName, colNames));
return results;
}
});
}
public List<String> getAllKeys(final ColumnFamily colFamily) throws HectorException {
return execute(new Command<List<String>>() {
public List<String> execute(KeyspaceService ks) throws HectorException {
return _getAllKeys(colFamily, ks);
}
});
}
/**
* @param colFamily
* @param ks
* @return
*/
private List<String> _getAllKeys(final ColumnFamily colFamily, final KeyspaceService ks) {
final int count = 1000; // read 1000 keys at a time
KeyRange keyRange = new KeyRange();
keyRange.setStart_key("");
keyRange.setEnd_key("");
keyRange.setCount(count);
ColumnParent cp = new ColumnParent(colFamily.toString());
SlicePredicate slicePredicate = new SlicePredicate();
SliceRange sliceRange = new SliceRange();
sliceRange.setStart(new byte[0]);
sliceRange.setFinish(new byte[0]);
sliceRange.setCount(1); // only get the first column
slicePredicate.setSlice_range(sliceRange);
List<String> all = new ArrayList<String>();
do {
LinkedHashMap<String, List<Column>> data = ks.getRangeSlices(cp, slicePredicate, keyRange);
final int size = data.size();
String last = null;
for (String each : data.keySet()) { // TODO Note: skip empty keys here
if (!data.get(each).isEmpty())
all.add(each);
last = each;
}
if (size < count) // end reached
break;
else
// continue to read more
keyRange.setStart_key(last);
} while (true);
return all;
}
public Map<String, List<Column>> getKeysAndColumns(final ColumnFamily colFamily, final String start, final String end,
final int count, final Object superColName, final List<Object> colNames, final Object colStart, final Object colFinish,
final int colCount, final boolean colReversed) throws HectorException {
if (count <= 1)
throw new IllegalArgumentException("count must be bigger than 1!");
return execute(new Command<Map<String, List<Column>>>() {
public Map<String, List<Column>> execute(KeyspaceService ks) throws HectorException {
int _count = count;
KeyRange keyRange = new KeyRange();
keyRange.setStart_key(start == null ? "" : start);
keyRange.setEnd_key(end == null ? "" : end);
keyRange.setCount(_count);
ColumnParent cp = new ColumnParent(colFamily.toString());
SlicePredicate slicePredicate = new SlicePredicate();
if (superColName != null)
cp.setSuper_column(DBUtil.bytesForName(superColName));
if (colNames != null) {
for (Object cn : colNames)
slicePredicate.addToColumn_names(DBUtil.bytesForName(cn));
} else {
SliceRange sliceRange = new SliceRange();
sliceRange.setStart(DBUtil.bytesForName(colStart == null ? "" : colStart));
sliceRange.setFinish(DBUtil.bytesForName(colFinish == null ? "" : colFinish));
if (colCount > 0)
sliceRange.setCount(colCount);
sliceRange.setReversed(colReversed);
slicePredicate.setSlice_range(sliceRange);
}
Map<String, List<Column>> _results = new LinkedHashMap<String, List<Column>>();
do {
LinkedHashMap<String, List<Column>> data = ks.getRangeSlices(cp, slicePredicate, keyRange);
boolean allLoaded = data.size() < _count;
boolean emptyFound = false;
String last = null;
for (String key : data.keySet()) {
List<Column> cols = data.get(key);
if (cols.isEmpty()) { // TODO Notice: skip empty keys here (that have no columns)
emptyFound = true;
} else if (_results.size() < count) { // not enough keys read
_results.put(key, cols);
} else { // OK, now enough keys are read, set the flag for stopping reading more
allLoaded = true;
break;
}
last = key;
}
if (!allLoaded && emptyFound) { // some empty keys got, continue to find other keys
_results.remove(last);
keyRange.setStart_key(last);
_count = count - _results.size(); // number of more keys to read
if (_count < 2) // note, the count must be bigger than 1
_count = 2;
keyRange.setCount(_count);
} else {
break;
}
} while (true);
return _results;
}
});
}
public void deleteColumns(final ColumnFamily colFamily, final String key, final Object superColName, final List<Object> colNames)
throws HectorException { // TODO use batchMutation instead
if (colNames == null)
throw new IllegalArgumentException("You must specify the Columns to delete!");
execute(new Command<Void>() {
public Void execute(KeyspaceService ks) throws HectorException {
for (Object cn : colNames)
ks.remove(key, createColumnPath(colFamily, superColName, cn));
return null;
}
});
}
public void deleteSuperColumns(final ColumnFamily colFamily, final String key, final List<Object> superColNames)
throws HectorException { // TODO use batchMutation instead
if (superColNames == null)
throw new IllegalArgumentException("You must specify the Super Columns to delete!");
execute(new Command<Void>() {
public Void execute(KeyspaceService ks) throws HectorException {
for (Object scn : superColNames) {
if (scn != null)
ks.remove(key, createColumnPath(colFamily, scn, null));
}
return null;
}
});
}
public void deleteSuperColumns(final ColumnFamily colFamily, final String key, final SuperColumn[] superColumns)
throws HectorException { // TODO use batchMutation instead
if (superColumns == null)
throw new IllegalArgumentException("You must specify the Super Columns to delete!");
execute(new Command<Void>() {
public Void execute(KeyspaceService ks) throws HectorException {
for (SuperColumn sc : superColumns) {
if (sc != null)
ks.remove(key, createColumnPath(colFamily, sc.getName(), null));
}
return null;
}
});
}
/**
* Delete all (Super) Columns for a key
*/
public void deleteKey(ColumnFamily colFamily, String key) throws HectorException {
if (key == null)
throw new IllegalArgumentException("You must specify the Key to delete!");
delete(colFamily, key, null, null);
}
/**
* Delete a super column for a key
*/
public void deleteSuperColumn(ColumnFamily colFamily, String key, Object superColName) throws HectorException {
if (superColName == null)
throw new IllegalArgumentException("You must specify the SuperColumn to delete!");
delete(colFamily, key, superColName, null);
}
public void deleteColumn(ColumnFamily colFamily, String key, Object superColName, Object colName) throws HectorException {
if (colName == null)
throw new IllegalArgumentException("You must specify the Column to delete!");
delete(colFamily, key, superColName, colName);
}
public void deleteColumn(ColumnFamily colFamily, String key, Object colName) throws HectorException {
deleteColumn(colFamily, key, null, colName);
}
private void delete(final ColumnFamily colFamily, final String key, final Object superColName, final Object colName)
throws HectorException {
execute(new Command<Void>() {
public Void execute(KeyspaceService ks) throws HectorException {
ks.remove(key, createColumnPath(colFamily, superColName, colName));
return null;
}
});
}
protected <T> T execute(Command<T> command) throws HectorException {
return command.execute(dbConfig.host, dbConfig.port, dbConfig.keyspace);
}
protected ColumnPath createColumnPath(ColumnFamily colFamily, Object superColName, Object colName) {
ColumnPath columnPath = new ColumnPath(colFamily.toString());
if (superColName != null)
columnPath.setSuper_column(DBUtil.bytesForName(superColName));
if (colName != null)
columnPath.setColumn(DBUtil.bytesForName(colName));
return columnPath;
}
public DBConfig getDbConfig() {
return dbConfig;
}
public void setDbConfig(DBConfig dbConfig) {
this.dbConfig = dbConfig;
}
protected <T extends DBA> T createInstance(Class<T> cls) {
try {
return cls.getConstructor(DBConfig.class).newInstance(this.dbConfig);
} catch (Exception e) {
log.error("createInstance", e);
return null;
}
}
}