/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.constraint.impl;
import com.emc.storageos.db.client.impl.ColumnField;
import com.emc.storageos.db.client.impl.CompositeColumnNameSerializer;
import com.emc.storageos.db.client.impl.IndexColumnName;
import com.emc.storageos.db.client.impl.IndexColumnNameSerializer;
import com.emc.storageos.db.client.impl.RelationDbIndex;
import com.emc.storageos.db.client.model.DataObject;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.query.RowQuery;
import com.netflix.astyanax.util.TimeUUIDUtils;
import java.net.URI;
/**
* A containment constraint that returns only those elements from the index that were added between startTime and endTime
*/
public class TimedContainmentConstraintImpl extends ConstraintImpl<IndexColumnName> {
private static final long MILLIS_TO_MICROS = 1000L;
private final long startTimeMicros;
private final long endTimeMicros;
private URI indexKey;
private Class<? extends DataObject> entryType;
private final ColumnField field;
private Keyspace keyspace;
public TimedContainmentConstraintImpl(URI indexKey, long startTimeMicros, long endTimeMicros, Class<? extends DataObject> entryType,
ColumnField field) {
super(indexKey, entryType, field);
indexSerializer = IndexColumnNameSerializer.get();
this.startTimeMicros = startTimeMicros * MILLIS_TO_MICROS;
this.endTimeMicros = endTimeMicros * MILLIS_TO_MICROS;
this.indexKey = indexKey;
this.entryType = entryType;
this.field = field;
returnOnePage = true;
}
@Override
public void setKeyspace(Keyspace keyspace) {
this.keyspace = keyspace;
}
protected <T> void queryOnePage(final QueryResult<T> result) throws ConnectionException {
RowQuery<String, IndexColumnName> query = keyspace.prepareQuery(field.getIndexCF())
.getKey(indexKey.toString())
.withColumnRange(
CompositeColumnNameSerializer.get().buildRange()
.greaterThanEquals(entryType.getSimpleName())
.lessThanEquals(entryType.getSimpleName()));
QueryHitIterator<T, IndexColumnName> it = createQueryHitIterator(query, result);
query.autoPaginate(true);
it.prime();
result.setResult(it);
}
@Override
protected RowQuery<String, IndexColumnName> genQuery() {
RowQuery<String, IndexColumnName> query = keyspace
.prepareQuery(field.getIndexCF())
.getKey(indexKey.toString())
.withColumnRange(
CompositeColumnNameSerializer.get().buildRange()
.greaterThanEquals(entryType.getSimpleName())
.lessThanEquals(entryType.getSimpleName())
.limit(pageCount));
return query;
}
protected <T> QueryHitIterator<T,IndexColumnName> createQueryHitIterator(RowQuery<String, IndexColumnName> query, final QueryResult<T> result) {
return new FilteredQueryHitIterator<T, IndexColumnName>(query) {
@Override
protected T createQueryHit(Column<IndexColumnName> column) {
return result.createQueryHit(getURI(column), column.getName().getThree(), column.getName().getTimeUUID());
}
@Override
public boolean filter(Column<IndexColumnName> column) {
long columnTime = TimeUUIDUtils.getMicrosTimeFromUUID(column.getName().getTimeUUID());
// Filtering on startTime, startTime = -1 for no filtering
if (startTimeMicros > 0 && columnTime < startTimeMicros) {
return false;
}
// Filtering on endTime, endTime = -1 for no filtering
if (endTimeMicros > 0 && columnTime > endTimeMicros) {
return false;
}
return true;
}
};
}
@Override
protected <T> T createQueryHit(QueryResult<T> result, Column<IndexColumnName> column) {
return result.createQueryHit(getURI(column), column.getName().getThree(), column.getName().getTimeUUID());
}
@Override
protected URI getURI(Column<IndexColumnName> col) {
URI ret;
if (field.getIndex() instanceof RelationDbIndex) {
ret = URI.create(col.getName().getTwo());
} else {
ret = URI.create(col.getName().getFour());
}
return ret;
}
@Override
public Class<? extends DataObject> getDataObjectType() {
return field.getDataObjectType();
}
@Override
public boolean isValid() {
return this.indexKey!=null && !this.indexKey.toString().isEmpty();
}
}