package org.epics.archiverappliance.config;
import java.util.HashMap;
import org.apache.log4j.Logger;
import org.epics.archiverappliance.etl.ETLDest;
import org.epics.archiverappliance.etl.StorageMetrics;
/**
* POJO facilitating various optimizations for BPL that uses appliance wide information.
* The correct values for most of this is obtained by iterating thru the PVTypeInfo's and aggregating them.
* To improve performance for business logic that takes the entire appliance into consideration, a few aggregated parameters are stored and maintained here.
* There are no transactional guarantees with the information aggregated here; if the perfect/best information is desired, walk thru the PVTypeInfos.
* This is available within the appliance for that appliance.
* @author mshankar
*
*/
public class ApplianceAggregateInfo {
private double totalStorageRate;
private double totalEventRate;
private double totalPVCount;
private HashMap<String, Long> totalStorageImpact= new HashMap<String, Long>();
private static Logger logger = Logger.getLogger(DefaultConfigService.class.getName());
public ApplianceAggregateInfo clone() {
ApplianceAggregateInfo retval = new ApplianceAggregateInfo();
retval.totalStorageRate = this.totalStorageRate;
retval.totalEventRate = this.totalEventRate;
retval.totalPVCount = this.totalPVCount;
retval.totalStorageImpact = new HashMap<String, Long>();
for(String key : this.totalStorageImpact.keySet()) {
retval.totalStorageImpact.put(key, this.totalStorageImpact.get(key));
}
return retval;
}
public void addInfoForPV(String pvName, PVTypeInfo typeInfo, ConfigService configService) {
synchronized(this) {
totalStorageRate += typeInfo.getComputedStorageRate();
totalEventRate += typeInfo.getComputedEventRate();
totalPVCount++;
if(typeInfo.getDataStores() != null && typeInfo.getDataStores().length > 0) {
for(String dataStore : typeInfo.getDataStores()) {
try {
ETLDest etlDest = StoragePluginURLParser.parseETLDest(dataStore, configService);
if(etlDest instanceof StorageMetrics) {
StorageMetrics stMetrics = (StorageMetrics) etlDest;
String identity = stMetrics.getName();
double storageImpact = etlDest.getPartitionGranularity().getApproxSecondsPerChunk()*typeInfo.getComputedStorageRate();
if(!totalStorageImpact.containsKey(identity)) {
totalStorageImpact.put(identity, new Long(0));
}
long currentStorageImpact = totalStorageImpact.get(identity);
currentStorageImpact += storageImpact;
totalStorageImpact.put(identity, currentStorageImpact);
}
} catch(Exception ex) {
logger.error("Exception parsing storage metrics url " + dataStore, ex);
}
}
}
}
}
/**
* Gets the aggregated total computedStorageRate for this appliance
* @return totalStorageRate
*/
public double getTotalStorageRate() {
return totalStorageRate;
}
/**
* Gets the aggregated total computedEventRate for this appliance
* @return totalEventRate
*/
public double getTotalEventRate() {
return totalEventRate;
}
/**
* Gets the aggregated pv count for this appliance.
* @return totalPVCount
*/
public double getTotalPVCount() {
return totalPVCount;
}
public void setTotalStorageRate(double totalStorageRate) {
this.totalStorageRate = totalStorageRate;
}
public void setTotalEventRate(double totalEventRate) {
this.totalEventRate = totalEventRate;
}
public void setTotalPVCount(double totalPVCount) {
this.totalPVCount = totalPVCount;
}
/**
* The storage impact is the impact of a PV on the particular store.
* It is the product of the estimated storage rate and the partition granularity of the source.
* This returns the aggregated impact on the various stores on this appliance indexed by the identity of the store.
* @return totalStorageImpact
*/
public HashMap<String, Long> getTotalStorageImpact() {
return totalStorageImpact;
}
public void setTotalStorageImpact(HashMap<String, String> totalStorageImpact) {
// The JSON Encoder and Decoder can only understand a HashMap<String, String> so we override the set method to take on HashMap<String, String>
for(String id : totalStorageImpact.keySet()) {
String impact = totalStorageImpact.get(id);
try {
long impactLong = Long.parseLong(impact);
this.totalStorageImpact.put(id, impactLong);
} catch(NumberFormatException ex) {
logger.error("Exception parsing number " + impact, ex);
}
}
}
/**
* This returns a new ApplianceAggregateInfo that is the difference between this info and the other info.
* Used to maintain the delta of ApplianceAggregateInfo's between the periodic fetches of the CapacityPlanningMetricsPerApplianceForPV
* @param other ApplianceAggregateInfo
* @return ApplianceAggregateInfo
*/
public ApplianceAggregateInfo getDifference(ApplianceAggregateInfo other) {
ApplianceAggregateInfo retval = new ApplianceAggregateInfo();
retval.totalPVCount = this.totalPVCount - other.totalPVCount;
retval.totalEventRate = this.totalEventRate - other.totalEventRate;
retval.totalStorageRate = this.totalStorageRate - other.totalStorageRate;
if(logger.isDebugEnabled()) logger.debug("Returning " + retval.totalStorageRate + " this.totalStorageRate " + this.totalStorageRate + " other.totalStorageRate " + other.totalStorageRate);
for(String key : totalStorageImpact.keySet()) {
long si = totalStorageImpact.get(key);
if(other.totalStorageImpact.containsKey(key)) {
si = si - other.totalStorageImpact.get(key);
}
retval.totalStorageImpact.put(key, new Long(si));
}
return retval;
}
}