/*
* Copyright (c) 2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.util;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.emc.storageos.db.client.DbAggregatorItf;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.constraint.AggregatedConstraint;
import com.emc.storageos.db.client.constraint.AggregationQueryResultList;
import com.emc.storageos.db.client.constraint.AlternateIdConstraint;
import com.emc.storageos.db.client.constraint.Constraint;
import com.emc.storageos.db.client.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.impl.BulkDataObjQueryResultIterator;
import com.emc.storageos.db.client.impl.ColumnField;
import com.emc.storageos.db.client.impl.ColumnValue;
import com.emc.storageos.db.client.impl.CompositeColumnName;
import com.emc.storageos.db.client.impl.DataObjectType;
import com.emc.storageos.db.client.impl.TypeMap;
import com.emc.storageos.db.client.model.BlockMirror;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.DataObject;
import com.emc.storageos.db.client.model.ProtectionSet;
import com.emc.storageos.db.client.model.SMISProvider;
import com.emc.storageos.db.client.model.StorageHADomain;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StorageProvider;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedProtectionSet;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume;
import com.emc.storageos.db.exceptions.DatabaseException;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.Row;
public class CustomQueryUtility {
public static List<SMISProvider> getActiveSMISProvidersByProviderId(DbClient dbClient, String providerId) {
return queryActiveResourcesByConstraint(dbClient,
SMISProvider.class,
AlternateIdConstraint.Factory.getSMISProviderByProviderIDConstraint(providerId));
}
public static List<StorageProvider> getActiveStorageProvidersByProviderId(DbClient dbClient, String providerId) {
return queryActiveResourcesByConstraint(dbClient,
StorageProvider.class,
AlternateIdConstraint.Factory.getStorageProviderByProviderIDConstraint(providerId));
}
public static List<StorageProvider> getActiveStorageProvidersByInterfaceType(DbClient dbClient, String interfaceType) {
return queryActiveResourcesByConstraint(dbClient,
StorageProvider.class,
AlternateIdConstraint.Factory.getProviderByInterfaceTypeConstraint(interfaceType));
}
public static List<StorageSystem> getActiveStorageSystemByMgmAccessId(DbClient dbClient, String mgmId) {
return queryActiveResourcesByConstraint(dbClient,
StorageSystem.class,
AlternateIdConstraint.Factory.getStorageSystemByMgmtAccessPointConstraint(mgmId));
}
public static List<StorageSystem> getActiveStorageSystemByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
StorageSystem.class,
AlternateIdConstraint.Factory.getStorageSystemByNativeGuidConstraint(nativeGuid));
}
public static List<StoragePool> getActiveStoragePoolByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
StoragePool.class,
AlternateIdConstraint.Factory.getStoragePoolByNativeGuidConstraint(nativeGuid));
}
public static List<StoragePort> getActiveStoragePortByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
StoragePort.class,
AlternateIdConstraint.Factory.getStoragePortByNativeGuidConstraint(nativeGuid));
}
public static List<ProtectionSet> getActiveProtectionSetByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
ProtectionSet.class,
AlternateIdConstraint.Factory.getProtectionSetByNativeGuidConstraint(nativeGuid));
}
public static List<UnManagedProtectionSet> getUnManagedProtectionSetByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
UnManagedProtectionSet.class,
AlternateIdConstraint.Factory.getUnManagedProtectionSetByNativeGuidConstraint(nativeGuid));
}
public static List<UnManagedVolume> getUnManagedVolumeByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
UnManagedVolume.class,
AlternateIdConstraint.Factory.getUnManagedVolumeByNativeGuidConstraint(nativeGuid));
}
public static List<UnManagedProtectionSet> getUnManagedProtectionSetByUnManagedVolumeId(DbClient dbClient, String unManagedVolumeId) {
return queryActiveResourcesByConstraint(dbClient,
UnManagedProtectionSet.class,
AlternateIdConstraint.Factory.getUnManagedProtectionSetByUnManagedVolumeConstraint(unManagedVolumeId));
}
public static List<UnManagedProtectionSet> getUnManagedProtectionSetByManagedVolumeId(DbClient dbClient, String managedVolumeId) {
return queryActiveResourcesByConstraint(dbClient,
UnManagedProtectionSet.class,
AlternateIdConstraint.Factory.getUnManagedProtectionSetByManagedVolumeConstraint(managedVolumeId));
}
public static List<UnManagedProtectionSet> getUnManagedProtectionSetByProtectionSystem(DbClient dbClient, String protectionSystemUri) {
return queryActiveResourcesByConstraint(dbClient,
UnManagedProtectionSet.class,
AlternateIdConstraint.Factory.getUnManagedProtectionSetsByProtectionSystemUriConstraint(protectionSystemUri));
}
public static List<StorageHADomain> getActiveStorageHADomainByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
StorageHADomain.class,
AlternateIdConstraint.Factory.getStorageHADomainByNativeGuidConstraint(nativeGuid));
}
public static List<Volume> getActiveVolumeByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
Volume.class,
AlternateIdConstraint.Factory.getVolumeNativeGuidConstraint(nativeGuid));
}
public static List<BlockSnapshot> getActiveBlockSnapshotByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
BlockSnapshot.class,
AlternateIdConstraint.Factory.getBlockSnapshotsByNativeGuid(nativeGuid));
}
public static List<BlockMirror> getActiveBlockMirrorByNativeGuid(DbClient dbClient, String nativeGuid) {
return queryActiveResourcesByConstraint(dbClient,
BlockMirror.class,
AlternateIdConstraint.Factory.getMirrorByNativeGuid(nativeGuid));
}
public static <T extends DataObject> List<T> queryActiveResourcesByAltId(DbClient dbClient,
Class<T> clazz,
String columnField,
String altId) {
return queryActiveResourcesByConstraint(dbClient,
clazz,
AlternateIdConstraint.Factory.getConstraint(clazz, columnField, altId));
}
public static <T extends DataObject> List<T> queryActiveResourcesByRelation(DbClient dbClient,
URI parentID,
Class<T> childType,
String childField) {
return queryActiveResourcesByConstraint(dbClient, childType,
ContainmentConstraint.Factory.getContainedObjectsConstraint(parentID,
childType,
childField));
}
/**
* queries records based on a constraint; potential Out of Memory risk if too many records in results set
*
* @param dbClient
* @param clazz
* @param constraint
* @return
*/
public static <T extends DataObject> List<T> queryActiveResourcesByConstraint(DbClient dbClient, Class<T> clazz, Constraint constraint) {
URIQueryResultList list = new URIQueryResultList();
dbClient.queryByConstraint(constraint, list);
Iterator<T> resultsIt = dbClient.queryIterativeObjects(clazz, list);
List<T> objects = new ArrayList<T>();
while (resultsIt.hasNext()) {
T obj = resultsIt.next();
if (!obj.getInactive()) {
objects.add(obj);
}
}
return objects;
}
public static <T extends DataObject> SumPrimitiveFieldAggregator aggregateActiveObject(
DbClient dbClient, Class<T> clazz,
String[] fields, Iterator<URI> ids) {
Iterator<URI> activeIds;
if (ids != null) {
activeIds = queryIterativeActiveObjects(dbClient, clazz, ids);
}
else {
activeIds = dbClient.queryByType(clazz, true).iterator();
}
SumPrimitiveFieldAggregator aggregator = new SumPrimitiveFieldAggregator(clazz, fields);
dbClient.aggregateObjectField(clazz, activeIds, aggregator);
return aggregator;
}
public static <T extends DataObject> AggregatedValue aggregatedPrimitiveField(DbClient dbClient,
Class<T> clazz,
String groupField,
String groupValue,
String aggregatedField) {
AggregationQueryResultList queryResults = new AggregationQueryResultList();
dbClient.queryByConstraint(AggregatedConstraint.Factory.getAggregationConstraint(clazz, groupField, groupValue, aggregatedField),
queryResults);
Iterator<AggregationQueryResultList.AggregatedEntry> it = queryResults.iterator();
return getAggregatedValue(it);
}
public static <T extends DataObject> AggregatedValue aggregatedPrimitiveField(DbClient dbClient,
Class<T> clazz,
String aggregatedField) {
AggregationQueryResultList queryResults = new AggregationQueryResultList();
dbClient.queryByConstraint(AggregatedConstraint.Factory.getAggregationConstraint(clazz, aggregatedField),
queryResults);
Iterator<AggregationQueryResultList.AggregatedEntry> it = queryResults.iterator();
return getAggregatedValue(it);
}
public static <T extends DataObject> AggregatedValue getAggregatedValue(Iterator<AggregationQueryResultList.AggregatedEntry> it) {
AggregatedValue agg = new AggregatedValue();
while (it.hasNext()) {
AggregationQueryResultList.AggregatedEntry entry = it.next();
agg.value += agg.getDouble(entry.getValue());
agg.count++;
}
return agg;
}
public static <T extends DataObject> SumPrimitiveFieldAggregator aggregateActiveObject(
DbClient dbClient, Class<T> clazz, String[] fields) {
return aggregateActiveObject(dbClient, clazz, fields, null);
}
private static <T extends DataObject> List<URI> queryActiveObjects(DbClient dbClient, Class<T> clazz, List<URI> ids)
throws DatabaseException {
class SelectActiveObjects implements DbAggregatorItf {
private final List<URI> _activeObjects;
private final DataObjectType _doType;
private final String _field;
private final ColumnField _columnField;
public List<URI> getActive() {
return _activeObjects;
}
@Override
public String[] getAggregatedFields() {
return new String[] { _field };
}
public SelectActiveObjects(Class<? extends DataObject> clazz) {
_activeObjects = new ArrayList<URI>();
_doType = TypeMap.getDoType(clazz);
_field = "inactive";
_columnField = _doType.getColumnField(_field);
}
@Override
public void aggregate(Row<String, CompositeColumnName> row) {
if (row.getColumns().size() == 0) {
return;
}
Column<CompositeColumnName> column = row.getColumns().iterator().next();
Boolean value = (Boolean) ColumnValue.getPrimitiveColumnValue(column, _columnField.getPropertyDescriptor());
if (!value.booleanValue()) {
_activeObjects.add(URI.create(row.getKey()));
}
}
}
SelectActiveObjects selector = new SelectActiveObjects(clazz);
dbClient.aggregateObjectField(clazz, ids.iterator(), selector);
return selector.getActive();
}
public static <T extends DataObject> Iterator<URI> queryIterativeActiveObjects(final DbClient dbClient, final Class<T> clazz,
final Iterator<URI> ids)
throws DatabaseException {
if (!(ids.hasNext())) {
// nothing to do, just an empty list
return new ArrayList<URI>().iterator();
}
BulkDataObjQueryResultIterator<URI> bulkQueryIterator = new
BulkDataObjQueryResultIterator<URI>(ids) {
@Override
protected void run() throws DatabaseException {
currentIt = null;
getNextBatch();
while (!nextBatch.isEmpty()) {
List<URI> currBatchResults = queryActiveObjects(dbClient, clazz, nextBatch);
if (!currBatchResults.isEmpty()) {
currentIt = currBatchResults.iterator();
break;
}
getNextBatch();
}
}
};
return bulkQueryIterator;
}
private static List<URI> filterDataObjects(DbClient dbClient, Class<? extends DataObject> clazz, String field, List<URI> ids,
Set<String> values) {
FieldInSetAggregator aggr = new FieldInSetAggregator(clazz, values, field);
dbClient.aggregateObjectField(clazz, ids.iterator(), aggr);
return aggr.getAggregate();
}
public static Iterator<URI> filterDataObjectsFieldValueInSet(final DbClient dbClient,
final Class<? extends DataObject> clazz,
final String field,
final Iterator<URI> ids,
final Set<String> values)
throws DatabaseException {
if (!(ids.hasNext())) {
// nothing to do, just an empty list
return new ArrayList<URI>().iterator();
}
BulkDataObjQueryResultIterator<URI> bulkQueryIterator = new
BulkDataObjQueryResultIterator<URI>(ids) {
@Override
protected void run() throws DatabaseException {
currentIt = null;
getNextBatch();
while (!nextBatch.isEmpty()) {
List<URI> currBatchResults = filterDataObjects(dbClient, clazz, field, nextBatch, values);
if (!currBatchResults.isEmpty()) {
currentIt = currBatchResults.iterator();
break;
}
getNextBatch();
}
}
};
return bulkQueryIterator;
}
static public class AggregatedValue {
double value = 0.0;
long count = 0;
public long getCount() {
return count;
}
public double getValue() {
return value;
}
double getDouble(Object value) {
double val = 0;
if (value instanceof Integer) {
val = ((Integer) value).intValue();
} else if (value instanceof Long) {
val = ((Long) value).longValue();
} else if (value instanceof Byte) {
val = ((Byte) value).byteValue();
} else if (value instanceof Short) {
val = ((Short) value).shortValue();
} else if (value instanceof Float) {
val = ((Float) value).floatValue();
} else if (value instanceof Double) {
val = (Double) value;
} else {
throw new UnsupportedOperationException();
}
return val;
}
}
/**
* Returns a list from an iterator
* SHOULD ONLY BE USED ON ITERATORS KNOWN TO HAVE FEW ITEMS ONLY!!!!!
*
* @param itr the iterator
* @return a list of the iterator items. Empty list if the iterator is empty.
*/
public static <T extends Object> List<T> iteratorToList(Iterator<T> itr) {
List<T> list = new ArrayList<T>();
while (itr.hasNext()) {
list.add(itr.next());
}
return list;
}
}