/*
* Copyright (c) 2008-2012 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.server;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.SoftReference;
import java.net.URI;
import java.util.*;
import com.emc.storageos.db.client.impl.ColumnField;
import com.emc.storageos.db.client.impl.DataObjectType;
import com.emc.storageos.db.client.impl.DbClientImpl;
import com.emc.storageos.db.client.impl.IndexCleaner;
import com.emc.storageos.db.client.impl.IndexCleanupList;
import com.emc.storageos.db.client.impl.IndexColumnName;
import com.emc.storageos.db.client.impl.RowMutator;
import com.emc.storageos.db.client.impl.TypeMap;
import com.emc.storageos.db.client.model.UnManagedDiscoveredObjects.UnManagedVolume;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.Row;
import com.netflix.astyanax.model.Rows;
import com.netflix.astyanax.query.ColumnFamilyQuery;
import com.netflix.astyanax.util.TimeUUIDUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.TestDBClientUtils;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.constraint.*;
import com.emc.storageos.db.client.model.*;
import com.emc.storageos.db.client.util.CustomQueryUtility;
import com.emc.storageos.db.client.util.SumPrimitiveFieldAggregator;
import com.emc.storageos.db.server.DbClientTest;
public class PersistingChangesTest extends DbsvcTestBase {
private static final Logger _log = LoggerFactory.getLogger(PersistingChangesTest.class);
private String _stringValue = new String("isilon");
private URI _uriValue = URIUtil.createId(DataObject.class);
private NamedURI _namedURIValue = new NamedURI(_uriValue, _stringValue);
private Number _numValue = 0xffff;
private Date _dateValue = new Date();
private StringMap _mapValue = new StringMap();
private StringSet _setValue = new StringSet();
private OpStatusMap _opValue = new OpStatusMap();
private FSExportMap _fsExportValue = new FSExportMap();
private SMBShareMap _smbShareMapValue = new SMBShareMap();
private StringSetMap _setMapValue = new StringSetMap();
private ScopedLabel _scopedLabelValue = new ScopedLabel("foo", "bar");
private ScopedLabelSet _scopedLabelSet = new ScopedLabelSet();
private Calendar _calValue = Calendar.getInstance();
private DbClient dbClient;
@Before
public void setupTest() {
this.dbClient = super.getDbClient(new DbClientTest.DbClientImplUnitTester());
}
@After
public void teardown() {
if (this.dbClient instanceof DbClientTest.DbClientImplUnitTester) {
((DbClientTest.DbClientImplUnitTester) this.dbClient).removeAll();
}
}
private void initMapSet() {
// StoragePool.reservedCapacityMap expects map values can be parsed by Long.parse()
_mapValue.put("key1", "1");
_mapValue.put("key2", "2");
_setValue.add("key1");
_setValue.add("key2");
_opValue.put("key1", new Operation(Operation.Status.ready.name()));
_opValue.put("key2", new Operation(Operation.Status.pending.name()));
_fsExportValue.put("key1", new FileExport(Arrays.asList("a"), "b", "c", "d", "e", "z"));
_fsExportValue.put("key2", new FileExport(Arrays.asList("f"), "j", "k", "l", "m", "n"));
_smbShareMapValue.put("key1", new SMBFileShare("a", "b", "c", "d", 1));
_smbShareMapValue.put("key2", new SMBFileShare("e", "f", "g", "h", 1));
_setMapValue.put("key1", "value1");
_setMapValue.put("key1", "value2");
_setMapValue.put("key2", "value3");
// ScopedLabel.label must be at least 2 chars long or constraint queries will fail
_scopedLabelSet.add(new ScopedLabel("abcde", "fghij"));
_scopedLabelSet.add(new ScopedLabel("klmno", "pqrst"));
}
private <T extends DataObject> void setAll(Class<T> clazz, DataObject obj) throws Exception {
BeanInfo bInfo;
bInfo = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] pds = bInfo.getPropertyDescriptors();
Object objValue = null;
for (int i = 0; i < pds.length; i++) {
PropertyDescriptor pd = pds[i];
if (pd.getWriteMethod() == null) {
continue;
}
if (pd.getName().equals("class")) {
continue;
}
Class type = pd.getPropertyType();
if (type == String.class) {
objValue = _stringValue;
} else if (type == URI.class) {
objValue = _uriValue;
} else if (type == Byte.class) {
objValue = _numValue.byteValue();
} else if (type == Boolean.class) {
objValue = true;
} else if (type == Short.class) {
objValue = _numValue.shortValue();
} else if (type == Integer.class) {
objValue = _numValue.intValue();
} else if (type == Long.class) {
objValue = _numValue.longValue();
} else if (type == Float.class) {
objValue = _numValue.floatValue();
} else if (type == Double.class) {
objValue = _numValue.doubleValue();
} else if (type == Date.class) {
objValue = _dateValue;
} else if (type == StringMap.class) {
objValue = _mapValue;
} else if (type == StringSet.class) {
objValue = _setValue;
} else if (type == OpStatusMap.class) {
objValue = _opValue;
} else if (type == FSExportMap.class) {
objValue = _fsExportValue;
} else if (type == NamedURI.class) {
objValue = _namedURIValue;
} else if (type == SMBShareMap.class) {
objValue = _smbShareMapValue;
} else if (type == StringSetMap.class) {
objValue = _setMapValue;
} else if (type == ScopedLabel.class) {
objValue = _scopedLabelValue;
} else if (type == ScopedLabelSet.class) {
objValue = _scopedLabelSet;
} else if (type == Calendar.class) {
objValue = _calValue;
} else {
throw new IllegalArgumentException("type: " + type + "clazz: " + clazz);
}
pd.getWriteMethod().invoke(obj, objValue);
}
}
private <T extends DataObject> void getAllAndVerify(Class<T> clazz, DataObject obj) throws Exception {
BeanInfo bInfo;
bInfo = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] pds = bInfo.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
PropertyDescriptor pd = pds[i];
Object objValue = pd.getReadMethod().invoke(obj);
if (pd.getName().equals("class")) {
continue;
}
// StoragePool.getFreeCapacity() := StoragePool.setFreeCapacity() - sum(StoragePool.setReservedCapacityMap())
// Volume.getWWM() := upper(Volume.setWWM())
else if (clazz.equals(StoragePool.class) && pd.getName().equals("freeCapacity")
|| clazz.equals(Volume.class) && pd.getName().equals("WWN")) {
continue;
}
String errMsg = String.format("Class: %s field: %s value didn't match.", clazz.getName(), pd.getName());
Class type = pd.getPropertyType();
if (type == String.class) {
Assert.assertEquals(errMsg, _stringValue, objValue);
} else if (type == URI.class) {
Assert.assertEquals(errMsg, _uriValue, objValue);
} else if (type == Byte.class) {
Assert.assertEquals(errMsg, _uriValue, objValue);
} else if (type == Boolean.class) {
Assert.assertTrue(errMsg, (Boolean) objValue);
} else if (type == Short.class) {
Assert.assertEquals(errMsg, _numValue.shortValue(), objValue);
} else if (type == Integer.class) {
Assert.assertEquals(errMsg, _numValue.intValue(), objValue);
} else if (type == Long.class) {
Assert.assertEquals(errMsg, _numValue.longValue(), objValue);
} else if (type == Float.class) {
Assert.assertEquals(errMsg, _numValue.floatValue(), objValue);
} else if (type == Double.class) {
Assert.assertEquals(errMsg, _numValue.doubleValue(), objValue);
} else if (type == Date.class) {
Assert.assertEquals(errMsg, _dateValue, objValue);
} else if (type == StringMap.class) {
Assert.assertEquals(errMsg, _mapValue, objValue);
} else if (type == StringSet.class) {
Assert.assertEquals(errMsg, _setValue, objValue);
} else if (type == OpStatusMap.class) {
Assert.assertEquals(errMsg, _opValue, objValue);
} else if (type == FSExportMap.class) {
Assert.assertEquals(errMsg, _fsExportValue, objValue);
} else if (type == NamedURI.class) {
Assert.assertEquals(errMsg, _namedURIValue, objValue);
} else if (type == SMBFileShare.class) {
Assert.assertEquals(errMsg, _smbShareMapValue, objValue);
} else if (type == StringSetMap.class) {
Assert.assertEquals(errMsg, _setMapValue, objValue);
} else if (type == ScopedLabel.class) {
Assert.assertEquals(errMsg, _scopedLabelValue, objValue);
} else if (type == ScopedLabelSet.class) {
Assert.assertEquals(errMsg, _scopedLabelSet, objValue);
} else if (type == Calendar.class) {
Assert.assertEquals(errMsg, _calValue, objValue);
}
}
}
/**
* Set all fields on the object, persist it, query it back and verify field values
*/
private <T extends DataObject> void testSet(DbClient dbClient, Class<T> clazz) throws Exception {
T obj = clazz.newInstance();
setAll(clazz, obj);
dbClient.persistObject(obj);
DataObject qObj = dbClient.queryObject(clazz, obj.getId());
getAllAndVerify(clazz, qObj);
}
/**
* Tests all setters are working as expected
*
* @throws Exception
*/
@Test
public void testSets() throws Exception {
initMapSet();
testSet(this.dbClient, VirtualPool.class);
testSet(this.dbClient, VirtualArray.class);
testSet(this.dbClient, Network.class);
testSet(this.dbClient, FileShare.class);
testSet(this.dbClient, Project.class);
testSet(this.dbClient, Snapshot.class);
testSet(this.dbClient, StorageSystem.class);
testSet(this.dbClient, StoragePool.class);
testSet(this.dbClient, TenantOrg.class);
testSet(this.dbClient, Volume.class);
}
/**
* Tests the changes tracking and the logic of persisting only diffs is working as expected
*/
@Test
public void testPersistingChanges() throws Exception {
VirtualPool vpool = new VirtualPool();
vpool.setId(URIUtil.createId(VirtualPool.class));
vpool.setLabel("GOLD");
vpool.setType("file");
vpool.setProtocols(new StringSet());
this.dbClient.persistObject(vpool);
TenantOrg tenant = new TenantOrg();
tenant.setId(URIUtil.createId(TenantOrg.class));
tenant.setLabel("test tenant");
tenant.setRoleAssignments(new StringSetMap());
FileShare fs = new FileShare();
fs.setId(URIUtil.createId(FileShare.class));
fs.setLabel("fileshare");
fs.setCapacity(102400L);
fs.setVirtualPool(vpool.getId());
fs.setOpStatus(new OpStatusMap());
fs.setTenant(new NamedURI(tenant.getId(), fs.getLabel()));
Operation op = new Operation();
op.setStatus(Operation.Status.pending.name());
fs.getOpStatus().put("filesharereq", op);
dbClient.persistObject(fs);
fs.getOpStatus().put("filesharereq", op);
this.dbClient.persistObject(fs);
FileShare fsQ = this.dbClient.queryObject(FileShare.class, fs.getId());
FileShare fsE = this.dbClient.queryObject(FileShare.class, fs.getId());
// file share creation
Assert.assertEquals(fsQ.getId(), fs.getId());
Assert.assertEquals(fsQ.getLabel(), "fileshare");
Assert.assertEquals((long) fsQ.getCapacity(), 102400L);
Assert.assertEquals(fsQ.getVirtualPool(), vpool.getId());
Assert.assertEquals(fsQ.getOpStatus().get("filesharereq").getStatus(),
Operation.Status.pending.name());
fsQ.setMountPath("test/mount/path");
fsQ.setNativeGuid("nativeguid");
fsQ.setFsExports(new FSExportMap());
FileExport fsExport = new FileExport(Arrays.asList("client"), "storageport", "sys", "rw", "root", "nfs");
fsQ.getFsExports().put("fsexport1", fsExport);
op = new Operation();
op.setStatus(Operation.Status.ready.name());
fsQ.getOpStatus().put("filesharereq", op);
// request to add exports
Assert.assertEquals(fsE.getId(), fs.getId());
Assert.assertEquals(fsE.getLabel(), "fileshare");
Assert.assertEquals((long) fsE.getCapacity(), 102400L);
Assert.assertEquals(fsE.getVirtualPool(), vpool.getId());
Assert.assertEquals(fsE.getOpStatus().get("filesharereq").getStatus(),
Operation.Status.pending.name());
fsE.setLabel("changed label");
op = new Operation();
op.setStatus(Operation.Status.pending.name());
fsE.getOpStatus().put("adding export", op);
// persist - in reverse order
this.dbClient.persistObject(fsQ);
this.dbClient.persistObject(fsE);
// test create and update status objects
FileShare fs_tasks = new FileShare();
fs_tasks.setId(URIUtil.createId(FileShare.class));
fs_tasks.setLabel("fileshare1");
fs_tasks.setCapacity(102400L);
fs_tasks.setVirtualPool(vpool.getId());
fs_tasks.setOpStatus(new OpStatusMap());
Operation op1 = new Operation();
op1.setStatus(Operation.Status.pending.name());
op1.setDescription("sample description");
fs_tasks.getOpStatus().createTaskStatus("filesharereq2", op1);
fs_tasks.setTenant(new NamedURI(tenant.getId(), fs.getLabel()));
this.dbClient.persistObject(fs_tasks);
FileShare fsBeforeUpdate = this.dbClient.queryObject(FileShare.class, fs_tasks.getId());
Operation opActual = fsBeforeUpdate.getOpStatus().get("filesharereq2");
Assert.assertNotNull(opActual.getStartTime());
Assert.assertNull(opActual.getEndTime());
this.dbClient.updateTaskOpStatus(FileShare.class, fs_tasks.getId(), "filesharereq2", new Operation(Operation.Status.ready.name()));
FileShare fsAfterUpdate = this.dbClient.queryObject(FileShare.class, fs_tasks.getId());
opActual = fsAfterUpdate.getOpStatus().get("filesharereq2");
Assert.assertNotNull(opActual.getStartTime());
Assert.assertNotNull(opActual.getEndTime());
// make sure both changes exist
FileShare fsV = this.dbClient.queryObject(FileShare.class, fs.getId());
Assert.assertEquals(fsV.getId(), fs.getId());
Assert.assertEquals(fsV.getLabel(), "changed label");
Assert.assertEquals((long) fsV.getCapacity(), 102400L);
Assert.assertEquals(fsV.getVirtualPool(), vpool.getId());
Assert.assertEquals(fsV.getOpStatus().get("filesharereq").getStatus(),
Operation.Status.ready.name());
Assert.assertEquals(fsV.getOpStatus().get("adding export").getStatus(),
Operation.Status.pending.name());
Assert.assertEquals(fsV.getNativeGuid(), "nativeguid");
Assert.assertEquals(fsV.getFsExports().get("fsexport1"), fsExport);
Assert.assertEquals(fsV.getMountPath(), "test/mount/path");
// update from StringMap
op = new Operation();
op.setStatus(Operation.Status.error.name());
fsV.getOpStatus().put("filesharereq", op);
this.dbClient.persistObject(fsV);
FileShare fs1 = this.dbClient.queryObject(FileShare.class, fs.getId());
Assert.assertEquals(Operation.Status.error.name(),
fs1.getOpStatus().get("filesharereq").getStatus());
Assert.assertEquals(Operation.Status.pending.name(),
fs1.getOpStatus().get("adding export").getStatus());
// SetMap tests
StringSetMap expected = new StringSetMap();
String indexkey1 = "indexkey1";
expected.put(indexkey1, "role1");
tenant.addRole(indexkey1, "role1");
expected.put(indexkey1, "role2");
tenant.addRole(indexkey1, "role2");
expected.put("indexkey2", "role3");
tenant.addRole("indexkey2", "role3");
this.dbClient.persistObject(tenant);
TenantOrg read = this.dbClient.queryObject(TenantOrg.class, tenant.getId());
Assert.assertEquals(expected, read.getRoleAssignments());
read.removeRole("indexkey2", "role3");
this.dbClient.persistObject(read);
class PermResults extends QueryResultList<URI> {
StringSetMap permissionsMap = new StringSetMap();
@Override
public URI createQueryHit(URI uri) {
// none
return uri;
}
@Override
public URI createQueryHit(URI uri, String permission, UUID timestamp) {
permissionsMap.put(uri.toString(), permission);
return uri;
}
@Override
public URI createQueryHit(URI uri, Object entry) {
return createQueryHit(uri);
}
public StringSetMap getPermissionsMap() {
return permissionsMap;
}
}
PermResults results = new PermResults();
this.dbClient.queryByConstraint(
ContainmentPermissionsConstraint.Factory.getTenantsWithPermissionsConstraint(
indexkey1), results);
expected = new StringSetMap();
expected.put(tenant.getId().toString(), "role1");
expected.put(tenant.getId().toString(), "role2");
for (Iterator<URI> iterator = results.iterator(); iterator.hasNext(); iterator.next()) {
;
}
Assert.assertEquals(expected, results.getPermissionsMap());
// just remove
expected = new StringSetMap();
expected.put(indexkey1, "role1");
expected.put(indexkey1, "role2");
read = this.dbClient.queryObject(TenantOrg.class, tenant.getId());
Assert.assertEquals(expected, read.getRoleAssignments());
read.removeRole(indexkey1, "role2");
this.dbClient.updateAndReindexObject(read);
PermResults newResults = new PermResults();
this.dbClient.queryByConstraint(
ContainmentPermissionsConstraint.Factory.getTenantsWithPermissionsConstraint(
indexkey1), newResults);
for (Iterator<URI> iterator = newResults.iterator(); iterator.hasNext(); iterator.next()) {
;
}
expected = new StringSetMap();
expected.put(tenant.getId().toString(), "role1");
Assert.assertEquals(expected, newResults.getPermissionsMap());
// query
TenantOrg tenant2 = new TenantOrg();
tenant2.setId(URIUtil.createId(TenantOrg.class));
tenant2.setLabel("test tenant2");
this.dbClient.updateAndReindexObject(tenant2);
List<URI> uris = new ArrayList<URI>();
uris.add(tenant.getId());
uris.add(tenant2.getId());
List<TenantOrg> tenantOrgs = this.dbClient.queryObjectField(TenantOrg.class, "label", uris);
Assert.assertTrue(tenantOrgs.size() == 2);
for (TenantOrg each : tenantOrgs) {
Assert.assertTrue((each.getId().equals(tenant.getId()) && each.getLabel().equals("test tenant")) ||
(each.getId().equals(tenant2.getId()) && each.getLabel().equals("test tenant2")));
}
final int count = 1000;
final int indexCount = 10;
String key = "scale-test-index-key ";
String val = "scale-test-index-value ";
String key2 = "scale-test-index-key2 ";
String val2 = "scale-test-index-value2 ";
List<URI> uriList = new ArrayList<URI>(count);
long createTime = 0;
long updateTime = 0;
long updateTime2 = 0;
long updateTime3 = 0;
for (int i = 0; i < count; i++) {
long startTime = System.currentTimeMillis();
TenantOrg t = new TenantOrg();
t.setId(URIUtil.createId(TenantOrg.class));
t.setLabel("test tenant " + i);
t.setRoleAssignments(new StringSetMap());
for (int j = 0; j < indexCount; j++) {
t.addRole(key + j, val + j);
}
this.dbClient.persistObject(t);
createTime += System.currentTimeMillis() - startTime;
uriList.add(t.getId());
// update 1 - index modifications
startTime = System.currentTimeMillis();
TenantOrg t2 = new TenantOrg();
t2.setId(t.getId());
for (int j = 0; j < indexCount; j++) {
t2.removeRole(key + j, val + j);
t2.addRole(key2 + j, val2 + j);
}
this.dbClient.updateAndReindexObject(t2);
updateTime += System.currentTimeMillis() - startTime;
// update 2 - label modification
startTime = System.currentTimeMillis();
t2 = new TenantOrg();
t2.setId(t.getId());
t2.setLabel(t.getLabel() + " modified");
this.dbClient.updateAndReindexObject(t2);
updateTime2 += System.currentTimeMillis() - startTime;
// update 3 - non-indexed field modification
startTime = System.currentTimeMillis();
t2 = new TenantOrg();
t2.setId(t.getId());
t2.setDescription("test tenant description");
this.dbClient.updateAndReindexObject(t2);
updateTime3 += System.currentTimeMillis() - startTime;
}
_log.info("Total objects created: " + count);
_log.info("Total create time: " + createTime + "msec");
_log.info("Total update time (multiple index fields): " + updateTime + "msec");
_log.info("Total update time (label only): " + updateTime2 + "msec");
_log.info("Total update time (non indexed field): " + updateTime3 + "msec");
class CountResults extends QueryResultList<URI> {
public int got = 0;
@Override
public URI createQueryHit(URI uri) {
// none
return uri;
}
@Override
public URI createQueryHit(URI uri, String permission, UUID timestamp) {
got++;
return uri;
}
@Override
public URI createQueryHit(URI uri, Object entry) {
return createQueryHit(uri);
}
public void verify() {
Assert.assertEquals(count, got);
}
}
for (int i = 0; i < indexCount; i++) {
CountResults countResults = new CountResults();
this.dbClient.queryByConstraint(
ContainmentPermissionsConstraint.Factory.getTenantsWithPermissionsConstraint(
key2 + i), countResults);
for (Iterator<URI> iterator = countResults.iterator(); iterator.hasNext(); iterator.next()) {
;
}
countResults.verify();
}
// test decommissioned index
tenant = this.dbClient.queryObject(TenantOrg.class, tenant.getId());
tenant.setInactive(true);
tenant2 = this.dbClient.queryObject(TenantOrg.class, tenant2.getId());
tenant2.setInactive(true);
this.dbClient.persistObject(tenant, tenant2);
URIQueryResultList list = new URIQueryResultList();
this.dbClient.queryByConstraint(
DecommissionedConstraint.Factory.getDecommissionedObjectsConstraint(
TenantOrg.class, 0), list);
List<URI> gotUris = new ArrayList<URI>();
for (Iterator<URI> iterator = list.iterator(); iterator.hasNext();) {
gotUris.add(iterator.next());
}
Assert.assertTrue(gotUris.size() >= 2);
Assert.assertTrue(gotUris.contains(tenant.getId()));
Assert.assertTrue(gotUris.contains(tenant2.getId()));
// test time slicing - 1
long nowTimeUsec = TimeUUIDUtils.getMicrosTimeFromUUID(TimeUUIDUtils.getUniqueTimeUUIDinMicros());
list = new URIQueryResultList();
this.dbClient.queryByConstraint(
DecommissionedConstraint.Factory.getDecommissionedObjectsConstraint(
TenantOrg.class, nowTimeUsec), list);
gotUris = new ArrayList<URI>();
for (Iterator<URI> iterator = list.iterator(); iterator.hasNext();) {
gotUris.add(iterator.next());
}
Assert.assertTrue(gotUris.size() >= 2);
Assert.assertTrue(gotUris.contains(tenant.getId()));
Assert.assertTrue(gotUris.contains(tenant2.getId()));
// test time slicing - 2
list = new URIQueryResultList();
this.dbClient.queryByConstraint(
DecommissionedConstraint.Factory.getDecommissionedObjectsConstraint(
TenantOrg.class, nowTimeUsec - (60 * 1000 * 1000)), list);
gotUris = new ArrayList<URI>();
for (Iterator<URI> iterator = list.iterator(); iterator.hasNext();) {
gotUris.add(iterator.next());
}
Assert.assertEquals(0, gotUris.size());
// test remove object
((DbClientImpl)dbClient).internalRemoveObjects(tenant, tenant2);
read = this.dbClient.queryObject(TenantOrg.class, tenant.getId());
Assert.assertNull(read);
read = this.dbClient.queryObject(TenantOrg.class, tenant2.getId());
Assert.assertNull(read);
newResults = new PermResults();
this.dbClient.queryByConstraint(
ContainmentPermissionsConstraint.Factory.getTenantsWithPermissionsConstraint(
indexkey1), newResults);
for (Iterator<URI> iterator = newResults.iterator(); iterator.hasNext(); iterator.next()) {
;
}
Assert.assertTrue(newResults.getPermissionsMap().isEmpty());
newResults = new PermResults();
this.dbClient.queryByConstraint(
ContainmentPermissionsConstraint.Factory.getTenantsWithPermissionsConstraint(
indexkey1), newResults);
for (Iterator<URI> iterator = newResults.iterator(); iterator.hasNext(); iterator.next()) {
;
}
expected = new StringSetMap();
Assert.assertEquals(expected, newResults.getPermissionsMap());
for (int i = 0; i < indexCount; i++) {
CountResults countResults = new CountResults();
this.dbClient.queryByConstraint(
ContainmentPermissionsConstraint.Factory.getTenantsWithPermissionsConstraint(
key2 + i), countResults);
for (Iterator<URI> iterator = countResults.iterator(); iterator.hasNext(); iterator.next()) {
;
}
countResults.verify();
}
}
/**
* Tests Constraint query
*/
@Test
public void testConstraintQuery() throws Exception {
List<StoragePool> pools = new ArrayList<StoragePool>();
for (int ii = 0; ii < 3; ii++) {
StoragePool pool = new StoragePool();
pool.setId(URIUtil.createId(VirtualPool.class));
pool.setLabel("POOL_" + ii);
this.dbClient.persistObject(pool);
pools.add(pool);
}
List<VirtualPool> vpools = new ArrayList<VirtualPool>();
for (int ii = 0; ii < 2; ii++) {
VirtualPool vpool = new VirtualPool();
vpool.setId(URIUtil.createId(VirtualPool.class));
vpool.setLabel(ii == 0 ? "GOLD" : "SILVER");
vpool.setType("block");
vpool.setProtocols(new StringSet());
vpool.setMatchedStoragePools(new StringSet());
this.dbClient.persistObject(vpool);
vpools.add(vpool);
}
vpools.get(0).getMatchedStoragePools().add(pools.get(0).getId().toString());
vpools.get(0).getMatchedStoragePools().add(pools.get(1).getId().toString());
this.dbClient.persistObject(vpools.get(0));
vpools.get(1).getMatchedStoragePools().add(pools.get(1).getId().toString());
this.dbClient.persistObject(vpools.get(1));
URIQueryResultList cosResultList = new URIQueryResultList();
this.dbClient.queryByConstraint(ContainmentConstraint.Factory
.getMatchedPoolVirtualPoolConstraint(pools.get(0).getId()), cosResultList);
Iterator<URI> cosIter = cosResultList.iterator();
int idx = 0;
while (cosIter.hasNext()) {
URI cos = cosIter.next();
Assert.assertTrue(cos.equals(vpools.get(0).getId()));
idx++;
}
Assert.assertTrue(idx == 1);
cosResultList = new URIQueryResultList();
this.dbClient.queryByConstraint(ContainmentConstraint.Factory
.getMatchedPoolVirtualPoolConstraint(pools.get(1).getId()), cosResultList);
cosIter = cosResultList.iterator();
idx = 0;
while (cosIter.hasNext()) {
URI cos = cosIter.next();
Assert.assertTrue(cos.equals(vpools.get(0).getId()) ||
cos.equals(vpools.get(1).getId()));
idx++;
}
Assert.assertTrue(idx == 2);
cosResultList = new URIQueryResultList();
this.dbClient.queryByConstraint(ContainmentConstraint.Factory
.getMatchedPoolVirtualPoolConstraint(pools.get(2).getId()), cosResultList);
cosIter = cosResultList.iterator();
Assert.assertTrue(!cosIter.hasNext());
}
@Test
public void testAggregationQuery() throws Exception {
cleanupDataObjectCF(Volume.class);
Volume volume1 = new Volume();
URI id1 = URIUtil.createId(Volume.class);
URI pool1 = URIUtil.createId(StoragePool.class);
volume1.setId(id1);
volume1.setLabel("volume1");
volume1.setPool(pool1);
volume1.setInactive(false);
volume1.setAllocatedCapacity(1000L);
volume1.setProvisionedCapacity(2000L);
Volume volume2 = new Volume();
URI id2 = URIUtil.createId(Volume.class);
URI pool2 = URIUtil.createId(StoragePool.class);
volume2.setId(id2);
volume2.setLabel("volume2");
volume2.setPool(pool2);
volume2.setInactive(true);
volume2.setAllocatedCapacity(2000L);
volume2.setProvisionedCapacity(4000L);
Volume volume3 = new Volume();
URI id3 = URIUtil.createId(Volume.class);
URI pool3 = URIUtil.createId(StoragePool.class);
volume3.setId(id3);
volume3.setLabel("volume3");
// volume3.setInactive(false); // by default it should be treated as active.
volume3.setPool(pool3);
volume3.setAllocatedCapacity(4000L);
volume3.setProvisionedCapacity(8000L);
Volume volume4 = new Volume();
URI id4 = URIUtil.createId(Volume.class);
volume4.setId(id4);
volume4.setLabel("volume4");
// volume4.setInactive(false); // by default it should be treated as active.
volume4.setPool(pool3);
volume4.setAllocatedCapacity(4500L);
volume4.setProvisionedCapacity(9500L);
List<URI> allIds = new ArrayList<URI>();
allIds.add(id1);
allIds.add(id2);
allIds.add(id3);
allIds.add(id4);
Set<String> pools = new HashSet<String>();
pools.add(pool2.toString());
pools.add(pool3.toString());
this.dbClient.createObject(volume1, volume2, volume3, volume4);
// count the total number of records
List<URI> allVol = this.dbClient.queryByType(Volume.class, false);
Assert.assertEquals("# of Volume objects in DB is not as expected", 4, TestDBClientUtils.size(allVol));
SumPrimitiveFieldAggregator aggregator = CustomQueryUtility.aggregateActiveObject(
this.dbClient, Volume.class, new String[] { "allocatedCapacity" });
Assert.assertTrue(aggregator.getRecordNum() == 3);
Assert.assertTrue((long) aggregator.getAggregate("allocatedCapacity") == 9500L);
aggregator = CustomQueryUtility.aggregateActiveObject(
this.dbClient, Volume.class,
new String[] { "allocatedCapacity" });
Assert.assertTrue(aggregator.getRecordNum() == 3);
Assert.assertTrue((long) aggregator.getAggregate("allocatedCapacity") == 9500L);
aggregator = CustomQueryUtility.aggregateActiveObject(
this.dbClient, Volume.class,
new String[] { "provisionedCapacity" });
Assert.assertTrue((long) aggregator.getAggregate("provisionedCapacity") == 19500L);
Iterator<URI> iter = CustomQueryUtility.filterDataObjectsFieldValueInSet(
this.dbClient, Volume.class,
"pool", allIds.iterator(), pools);
List<URI> volFromPools = new ArrayList<URI>();
while (iter.hasNext()) {
volFromPools.add(iter.next());
}
aggregator = CustomQueryUtility.aggregateActiveObject(
this.dbClient, Volume.class,
new String[] { "allocatedCapacity" }, volFromPools.iterator());
Assert.assertTrue(aggregator.getRecordNum() == 2);
Assert.assertTrue((long) aggregator.getAggregate("allocatedCapacity") == 8500L);
aggregator = CustomQueryUtility.aggregateActiveObject(
this.dbClient, Volume.class,
new String[] { "provisionedCapacity" }, volFromPools.iterator());
Assert.assertTrue((long) aggregator.getAggregate("provisionedCapacity") == 17500L);
}
@Test
public void testQueryByFieldThenDelete() throws Exception {
Volume volume = new Volume();
URI id = URIUtil.createId(Volume.class);
URI pool = URIUtil.createId(StoragePool.class);
volume.setId(id);
volume.setLabel("volume");
volume.setPool(pool);
volume.setNativeGuid("native_guid");
volume.setNativeId("native_id");
volume.setCompositionType("compositionType");
volume.setInactive(false);
volume.setAllocatedCapacity(1000L);
volume.setProvisionedCapacity(2000L);
dbClient.updateObject(volume);
List<Volume> volumes = dbClient.queryObjectField(Volume.class, "compositionType", Arrays.asList(id));
Assert.assertTrue(volumes.size() == 1);
Assert.assertEquals("compositionType", volumes.get(0).getCompositionType());
dbClient.markForDeletion(volumes.get(0));
URIQueryResultList result1 = new URIQueryResultList();
dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getVolumeNativeGuidConstraint(volume.getNativeGuid()), result1);
Assert.assertFalse(result1.iterator().hasNext());
URIQueryResultList result2 = new URIQueryResultList();
dbClient.queryByConstraint(AlternateIdConstraint.Factory
.getVolumeNativeIdConstraint(volume.getNativeId()), result2);
Assert.assertFalse(result2.iterator().hasNext());
Volume queryVolumeResult = (Volume) dbClient.queryObject(id);
Assert.assertTrue(queryVolumeResult == null || queryVolumeResult.getInactive());
}
@Test
public void testCleanupSoftReference() throws ConnectionException {
Volume volume = new Volume();
URI id = URIUtil.createId(Volume.class);
URI pool = URIUtil.createId(StoragePool.class);
volume.setId(id);
volume.setLabel("origin");
volume.setPool(pool);
volume.setNativeGuid("native_guid");
volume.setNativeId("native_id");
volume.setCompositionType("compositionType");
volume.setInactive(false);
volume.setAllocatedCapacity(1000L);
volume.setProvisionedCapacity(2000L);
dbClient.updateObject(volume);
// Search the label index directly
String labelFieldName = "label";
int labelCount = getIndexRecordCount(labelFieldName);
Assert.assertEquals(2, labelCount); // By default, label index contains one record for VirtualDataCenter
List<URI> volumes = dbClient.queryByType(Volume.class, true);
int size = 0;
for (URI uri : volumes) {
Volume entry = dbClient.queryObject(Volume.class, uri);
_log.info("{}, URI={}, Label={}", ++size, uri, entry.getLabel());
Assert.assertEquals("origin", entry.getLabel());
}
Assert.assertEquals(1, size);
_log.info("\nStart to update with new label");
// Mock warning when listToCleanRef is null in indexCleaner
this.dbClient = super.getDbClient(new DbClientTest.DbClientImplUnitTester() {
@Override
public synchronized void start() {
super.start();
_indexCleaner = new IndexCleaner() {
@Override
public void cleanIndex(RowMutator mutator, DataObjectType doType, SoftReference<IndexCleanupList> listToCleanRef) {
listToCleanRef.clear();
super.cleanIndex(mutator, doType, listToCleanRef);
}
};
}
});
volume = dbClient.queryObject(Volume.class, id);
volume.setLabel("new");
dbClient.updateObject(volume);
// Search the label index directly
labelCount = getIndexRecordCount(labelFieldName);
Assert.assertEquals(3, labelCount); // We mocked indexCleaner, so that old label index couldn't be removed, still in DB
volumes = dbClient.queryByType(Volume.class, true);
size = 0;
for (URI uri : volumes) {
Volume entry = dbClient.queryObject(Volume.class, uri);
_log.info("{}, URI={}, Label={}", ++size, uri, entry.getLabel());
Assert.assertEquals("new", entry.getLabel());
}
Assert.assertEquals(1, size);
// Remove the object
_log.info("\nStart to remove volume");
this.dbClient = super.getDbClient(new DbClientTest.DbClientImplUnitTester());
volume = dbClient.queryObject(Volume.class, id);
dbClient.removeObject(volume);
// Search the label index directly
labelCount = getIndexRecordCount(labelFieldName);
Assert.assertEquals(1, labelCount);// All the label index related to volume should be removed.
volumes = dbClient.queryByType(Volume.class, true);
size = 0;
for (URI uri : volumes) {
Volume entry = dbClient.queryObject(Volume.class, uri);
_log.info("{}, URI={}, Label={}", ++size, uri, entry.getLabel());
}
Assert.assertEquals(0, size);
}
private int getIndexRecordCount(String fieldName) throws ConnectionException {
Keyspace keyspace = ((DbClientTest.DbClientImplUnitTester) dbClient).getLocalContext().getKeyspace();
DataObjectType doType = TypeMap.getDoType(Volume.class);
ColumnField field = doType.getColumnField(fieldName);
ColumnFamilyQuery<String, IndexColumnName> query = keyspace.prepareQuery(field.getIndexCF());
OperationResult<Rows<String, IndexColumnName>> result = query.getAllRows().execute();
int count = 0;
for (Row<String, IndexColumnName> row : result.getResult()) {
_log.debug("{}, RowKey={}, Columns Size={}", ++count, row.getKey(), row.getColumns().size());
for (Column<IndexColumnName> column : row.getColumns()) {
_log.debug("\t, Column Name={}, String Value={}.", column.getName(), column.getStringValue());
}
}
return count;
}
@Test
public void testStringSetMapRemove() throws Exception {
UnManagedVolume unManagedVolume = new UnManagedVolume();
URI id = URIUtil.createId(UnManagedVolume.class);
unManagedVolume.setId(id);
StringSet set1 = new StringSet();
set1.add("test1");
set1.add("test2");
set1.add("test3");
set1.add("test4");
StringSet set2 = new StringSet();
set2.add("test5");
set2.add("test6");
set2.add("test7");
set2.add("test8");
String key1 = "key1";
String key2 = "key2";
unManagedVolume.putVolumeInfo("key1", set1);
unManagedVolume.putVolumeInfo("key2", set2);
dbClient.createObject(unManagedVolume);
unManagedVolume = dbClient.queryObject(UnManagedVolume.class, id);
Assert.assertTrue(unManagedVolume.getVolumeInformation().containsKey(key1));
Assert.assertTrue(unManagedVolume.getVolumeInformation().containsKey(key2));
unManagedVolume.getVolumeInformation().remove(key1);
unManagedVolume.getVolumeInformation().get(key2).remove("test6");
dbClient.updateObject(unManagedVolume);
unManagedVolume = dbClient.queryObject(UnManagedVolume.class, id);
Assert.assertFalse(unManagedVolume.getVolumeInformation().containsKey(key1));
Assert.assertTrue(unManagedVolume.getVolumeInformation().get(key2).contains("test7"));
Assert.assertFalse(unManagedVolume.getVolumeInformation().get(key2).contains("test6"));
}
@Test
public void testRemoveObject() throws Exception {
Task task = new Task();
task.setId(URIUtil.createId(Task.class));
task.setLabel("task1");
Volume volume = new Volume();
volume.setId(URIUtil.createId(Volume.class));
volume.setLabel("Volume");
dbClient.updateObject(task, volume);
dbClient.removeObject(task, volume);
Assert.assertNull(dbClient.queryObject(Task.class, task.getId()));
Volume result = dbClient.queryObject(Volume.class, volume.getId());
Assert.assertEquals(volume.getId(), result.getId());
Assert.assertEquals(volume.getLabel(), result.getLabel());
Assert.assertTrue(result.getInactive());
}
}