/*
* Copyright (c) 2008-2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.detailedDiscovery;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.cim.CIMArgument;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.plugins.BaseCollectionException;
import com.emc.storageos.plugins.common.Constants;
import com.emc.storageos.plugins.common.PartitionManager;
import com.emc.storageos.plugins.common.domainmodel.Operation;
import com.emc.storageos.volumecontroller.impl.plugins.discovery.smis.processor.StorageProcessor;
import com.emc.storageos.volumecontroller.impl.smis.SmisConstants;
/**
* Processor to handle StorageSynchronized instances of single volume snapshots
* and update corresponding BlockSnapshots in ViPR
*
* Used in BLOCK_SNAPSHOTS discovery only
*/
public class SnapshotReplicationRelationshipProcessor extends StorageProcessor {
private final static Logger _logger = LoggerFactory
.getLogger(SnapshotReplicationRelationshipProcessor.class);
private static final String COPY_STATE = "CopyState";
private static final String EMC_RELATIONSHIP_NAME = "EMCRelationshipName";
private static final String EMC_COPY_STATE_DESC = "EMCCopyStateDesc";
private static final String INACTIVE = "INACTIVE";
private static final String COPY_STATE_SYNCHRONIZED = "4";
private static final String BLOCK_SNAPSHOT = "BlockSnapshot";
private PartitionManager _partitionManager;
private int _partitionSize;
private DbClient _dbClient;
private Map<String, Map<String, String>> _syncAspectMap;
private List<BlockSnapshot> _updateSnapshotList;
@SuppressWarnings("unchecked")
@Override
public void processResult(Operation operation, Object resultObj,
Map<String, Object> keyMap) throws BaseCollectionException {
_logger.debug("Calling SnapshotReplicationRelationshipProcessor");
_dbClient = (DbClient) keyMap.get(Constants.dbClient);
_syncAspectMap = (Map<String, Map<String, String>>) keyMap
.get(Constants.SNAPSHOT_NAMES_SYNCHRONIZATION_ASPECT_MAP);
_updateSnapshotList = new ArrayList<BlockSnapshot>();
_partitionSize = getPartitionSize(keyMap);
CIMInstance[] instances = (CIMInstance[]) getFromOutputArgs(
(CIMArgument[]) resultObj, SmisConstants.SYNCHRONIZATIONS);
if (instances == null) {
_logger.info("No {} returned", SmisConstants.SYNCHRONIZATIONS);
return;
}
_logger.info("Total StorageSynchronized instances {}", instances.length);
processInstances(instances);
if (!_updateSnapshotList.isEmpty()) {
_partitionManager.updateInBatches(_updateSnapshotList,
_partitionSize, _dbClient, BLOCK_SNAPSHOT);
}
}
private void processInstances(CIMInstance[] instances) {
for (CIMInstance instance : instances) {
try {
CIMObjectPath targetPath = (CIMObjectPath) instance
.getPropertyValue(Constants._SyncedElement);
String nativeGuid = getVolumeNativeGuid(targetPath);
_logger.info("Processing snapshot {}", nativeGuid);
BlockSnapshot snapshot = checkSnapShotExistsInDB(nativeGuid,
_dbClient);
if (snapshot != null && !snapshot.hasConsistencyGroup()) {
if (updateSettingsInstance(instance, snapshot) ||
updateNeedsCopyToTarget(instance, snapshot) ||
updateIsSyncActive(instance, snapshot)) {
_logger.debug("Update Snapshot {}", snapshot.getLabel());
_updateSnapshotList.add(snapshot);
if (_updateSnapshotList.size() >= _partitionSize) {
_partitionManager.updateInBatches(_updateSnapshotList,
_partitionSize, _dbClient,
BLOCK_SNAPSHOT);
_updateSnapshotList.clear();
}
}
}
} catch (Exception e) {
_logger.error("Exception on processing instances", e);
}
}
}
private boolean updateSettingsInstance(CIMInstance syncInstance,
BlockSnapshot snapshot) {
CIMObjectPath sourcePath = (CIMObjectPath) syncInstance
.getPropertyValue(Constants._SystemElement);
String srcNativeGuid = getUnManagedVolumeNativeGuidFromVolumePath(sourcePath);
String relationshipName = getCIMPropertyValue(syncInstance,
EMC_RELATIONSHIP_NAME);
String syncAspect = null;
Map<String, String> aspectsForSource = _syncAspectMap.get(srcNativeGuid);
if (null != aspectsForSource) {
syncAspect = aspectsForSource.get(getSyncAspectMapKey(srcNativeGuid, relationshipName));
}
String valueInDb = snapshot.getSettingsInstance();
boolean isValueChanged = !(valueInDb == null ? syncAspect == null
: valueInDb.equals(syncAspect));
if (isValueChanged) {
snapshot.setSettingsInstance(syncAspect);
}
return isValueChanged;
}
private boolean updateNeedsCopyToTarget(CIMInstance syncInstance,
BlockSnapshot snapshot) {
String emcCopyState = getCIMPropertyValue(syncInstance,
EMC_COPY_STATE_DESC);
// for an inactive snapshot, needsCopyToTarget has to be set
boolean needsCopyToTarget = INACTIVE.equals(emcCopyState);
Boolean valueInDb = snapshot.getNeedsCopyToTarget();
boolean isValueChanged = valueInDb == null ? true
: valueInDb != needsCopyToTarget;
if (isValueChanged) {
snapshot.setNeedsCopyToTarget(needsCopyToTarget);
}
return isValueChanged;
}
private boolean updateIsSyncActive(CIMInstance syncInstance,
BlockSnapshot snapshot) {
String copyState = getCIMPropertyValue(syncInstance, COPY_STATE);
boolean inSync = COPY_STATE_SYNCHRONIZED.equals(copyState);
Boolean valueInDb = snapshot.getIsSyncActive();
boolean isValueChanged = valueInDb == null ? true : inSync != valueInDb
.booleanValue();
if (isValueChanged) {
snapshot.setIsSyncActive(inSync);
}
return isValueChanged;
}
public void setPartitionManager(PartitionManager partitionManager) {
_partitionManager = partitionManager;
}
}