/* * Copyright (c) 2008-2011 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.plugins.metering.smis.processor; import java.util.List; import java.util.Map; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import javax.cim.UnsignedInteger32; import javax.wbem.CloseableIterator; import javax.wbem.client.EnumerateResponse; import javax.wbem.client.WBEMClient; import com.emc.storageos.volumecontroller.impl.plugins.SMICommunicationInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.model.Stat; import com.emc.storageos.plugins.BaseCollectionException; import com.emc.storageos.plugins.common.Constants; import com.emc.storageos.plugins.common.Processor; import com.emc.storageos.plugins.common.domainmodel.Operation; /** * * Responsible for calculating Provisioned Capacity via Storage Pool Relations. * StoragaePool--->CIM_AllocatedFromStoragePool If, huge number of Volumes are * managed by Bourne, its better to get Volume Instances in bulk, i.e. via * Storage Pools rather than getting AllocatedFromStoragePool for each Volume. * ProvisionedCapacityProcessor- Responsible for calculating Provisioned * Capacity for Volume via Volume Relations Formula for calculating Provisioned * Capacity : NumberofBlocks * BlockSize. Synchronized Block is not needed for * either retrieving Metrics Object from Map or while adding provisioned * capacity to Metrics. as Each thread is responsible for handling a unique * Volume Instance which doesn't share any information across other threads. * To-Do: Currently, the underlying SBLIM library takes up the responsibility of * parsing CIMXML and provide us Instances back. These Instances are kept in * memory for further processing.Need to analyze the memory impact. If needed, * look for alternatives like using Native Heaps via EhCache, or Mem-cache */ public class CapacityPoolProcessor extends Processor { private static final int BATCH_SIZE = 200; private List<Object> _args; private Logger _logger = LoggerFactory.getLogger(CapacityPoolProcessor.class); @Override public void processResult( Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { EnumerateResponse<CIMInstance> volumeInstanceChunks = (EnumerateResponse<CIMInstance>) resultObj; WBEMClient client = SMICommunicationInterface.getCIMClient(keyMap); CloseableIterator<CIMInstance> volumeInstances = volumeInstanceChunks.getResponses(); try { processVolumeCapacity(volumeInstances, keyMap); while (!volumeInstanceChunks.isEnd()) { CIMObjectPath storagePoolPath = getObjectPathfromCIMArgument(_args); _logger.info("Processing Next Volume Chunk of size {}", BATCH_SIZE); volumeInstanceChunks = client.getInstancesWithPath( storagePoolPath, volumeInstanceChunks.getContext(), new UnsignedInteger32(BATCH_SIZE)); processVolumeCapacity(volumeInstanceChunks.getResponses(), keyMap); } } catch (Exception e) { _logger.error("Provisioned Capacity failure :", e); } finally { resultObj = null; if (null != volumeInstances) { volumeInstances.close(); } } } @Override protected void setPrerequisiteObjects(List<Object> arg0) throws BaseCollectionException { _args = arg0; } /** * Process volume capacity, iterates over the given chunk and process * each volume capacity. * * @param volumeInstances {@link CloseableIterator} instance * @param keyMap {@link Map} instance */ private void processVolumeCapacity( CloseableIterator<CIMInstance> volumeInstances, Map<String, Object> keyMap) { while (volumeInstances.hasNext()) { try { final CIMInstance volumeInstance = (CIMInstance) volumeInstances .next(); String key = null; String spaceConsumed = null; if (keyMap.containsKey(Constants.IS_NEW_SMIS_PROVIDER) && Boolean.valueOf(keyMap.get( Constants.IS_NEW_SMIS_PROVIDER).toString())) { key = createKeyfor8x(volumeInstance); spaceConsumed = volumeInstance .getProperty(_emcspaceConsumed).getValue() .toString(); } else { key = createKeyfromProps(volumeInstance); spaceConsumed = volumeInstance.getProperty(_spaceConsumed) .getValue().toString(); } Object value = getMetrics(keyMap, key); if (null == value) { keyMap.put(key, Long.parseLong(spaceConsumed)); } else if (value instanceof Stat) { Stat metrics = (Stat) value; metrics.setProvisionedCapacity(returnProvisionedCapacity( volumeInstance, keyMap)); metrics.setAllocatedCapacity(Long.parseLong(spaceConsumed)); } } catch (Exception ex) { // This check will make sure to skip unnecessary logs if (!(ex instanceof BaseCollectionException)) { _logger.error("Provisioned Capacity failure : ", ex); } } } } }