/*
* Copyright (c) 2008-2012 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.constraint.impl;
import java.net.URI;
import com.emc.storageos.db.client.model.NoInactiveIndex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.ColumnFamily;
import com.netflix.astyanax.query.RowQuery;
import com.netflix.astyanax.util.RangeBuilder;
import com.netflix.astyanax.util.TimeUUIDUtils;
import com.emc.storageos.db.client.constraint.DecommissionedConstraint;
import com.emc.storageos.db.client.impl.*;
import com.emc.storageos.db.client.model.DataObject;
/**
* Constrained query to get list of decommissioned object URIs of a given type
*/
public class DecommissionedConstraintImpl extends ConstraintImpl<IndexColumnName> implements DecommissionedConstraint {
private static final Logger log = LoggerFactory.getLogger(DecommissionedConstraintImpl.class);
private Keyspace _keyspace;
private final ColumnFamily<String, IndexColumnName> _cf;
private final String _rowKey;
private final long _timeToStartFrom;
private final Boolean _value;
private final Class<? extends DataObject> _entryType;
/*
* Constraint for listing all active objects of a given type with value true
* used by GC and token time indexing
*/
public DecommissionedConstraintImpl(Class<? extends DataObject> clazz, ColumnField field, long timeStart) {
super(clazz, field, timeStart);
indexSerializer = IndexColumnNameSerializer.get();
throwIfNoInactiveIndex(field);
_cf = field.getIndexCF();
_rowKey = clazz.getSimpleName();
_timeToStartFrom = timeStart;
_value = true;
_entryType = clazz;
}
/*
* Constraint for listing all objects of a given type with index value
* if value is null, gives full list for the type - used by queryByType.
*/
public DecommissionedConstraintImpl(Class<? extends DataObject> clazz, ColumnField field, Boolean value) {
super(clazz, field, value);
indexSerializer = IndexColumnNameSerializer.get();
throwIfNoInactiveIndex(field);
_cf = field.getIndexCF();
_rowKey = clazz.getSimpleName();
_timeToStartFrom = 0;
_value = value;
_entryType = clazz;
}
private void throwIfNoInactiveIndex(ColumnField field) {
if (field.getName().equals(DataObject.INACTIVE_FIELD_NAME)
&& field.getDataObjectType().getAnnotation(NoInactiveIndex.class) != null) {
throw new IllegalArgumentException(String.format("Class %s is marked with @NoInactiveIndex", field.getDataObjectType()
.getName()));
}
}
@Override
public void setKeyspace(Keyspace keyspace) {
_keyspace = keyspace;
}
@Override
protected <T> void queryOnePage(final QueryResult<T> result) throws ConnectionException {
if (_value != null) {
queryOnePageWithoutAutoPaginate(genQuery(), Boolean.toString(_value), result);
}
else {
queryOnePageWithAutoPaginate(genQuery(), result);
}
}
@Override
protected <T> void queryWithAutoPaginate(RowQuery<String, IndexColumnName> query, final QueryResult<T> result) {
query.autoPaginate(true);
FilteredQueryHitIterator<T, IndexColumnName> it;
if (_timeToStartFrom > 0) {
// time slice - get only older than _timeToStartFrom
it = new FilteredQueryHitIterator<T, IndexColumnName>(query) {
@Override
protected T createQueryHit(Column<IndexColumnName> column) {
return result.createQueryHit(URI.create(column.getName().getTwo()));
}
@Override
public boolean filter(Column<IndexColumnName> column) {
long timeMarked = TimeUUIDUtils.getMicrosTimeFromUUID(column.getName()
.getTimeUUID());
if (_timeToStartFrom >= timeMarked) {
return true;
}
return false;
}
};
} else {
// no time slicing - get all
it = new FilteredQueryHitIterator<T, IndexColumnName>(query) {
@Override
protected T createQueryHit(Column<IndexColumnName> column) {
return result.createQueryHit(URI.create(column.getName().getTwo()));
}
@Override
public boolean filter(Column<IndexColumnName> column) {
return true;
}
};
}
it.prime();
result.setResult(it);
}
@Override
protected URI getURI(Column<IndexColumnName> col) {
return URI.create(col.getName().getTwo());
}
@Override
protected <T> T createQueryHit(final QueryResult<T> result, Column<IndexColumnName> column) {
return result.createQueryHit(URI.create(column.getName().getTwo()));
}
@Override
protected RowQuery<String, IndexColumnName> genQuery() {
RowQuery<String, IndexColumnName> query;
if (_value == null) {
query = _keyspace.prepareQuery(_cf).getKey(_rowKey)
.withColumnRange(new RangeBuilder().setLimit(pageCount).build());
} else {
query = _keyspace.prepareQuery(_cf).getKey(_rowKey)
.withColumnRange(
CompositeColumnNameSerializer.get().buildRange()
.greaterThanEquals(_value.toString())
.lessThanEquals(_value.toString())
.limit(pageCount));
}
return query;
}
@Override
public Class<? extends DataObject> getDataObjectType() {
return _entryType;
}
@Override
public boolean isValid() {
return this._rowKey!=null && !this._rowKey.isEmpty();
}
}