package org.openstack.atlas.api.mgmt.helpers; import org.openstack.atlas.api.helpers.CalendarHelper; import org.openstack.atlas.service.domain.pojos.HostUsageRecord; import org.openstack.atlas.service.domain.usage.entities.HostUsage; import java.util.*; public final class HostUsageProcessor { /* This variable is used to determine if Zeus really got reset.*/ public static final long ZEUS_RESET_THRESHOLD_BYTES = 1073741824; // 1024 * 1024 * 1024 = 1073741824 => 1GB /* * NOTE: This method assumes that the usage records are sorted by ascending snapshot time */ public static List<HostUsageRecord> processRawHostUsageData(List<HostUsage> rawHostUsage) { List<HostUsageRecord> hostUsageRecords = new ArrayList<HostUsageRecord>(); if (rawHostUsage == null) return hostUsageRecords; Map<Integer, Map<Calendar, List<HostUsage>>> dailyHostUsageMap = convertRawUsageToMap(rawHostUsage); for (Integer hostId : dailyHostUsageMap.keySet()) { HostUsageRecord hostUsageRecord = new HostUsageRecord(); hostUsageRecord.setHostId(hostId); hostUsageRecord.setHostUsages(processDailyHostUsageMap(dailyHostUsageMap.get(hostId))); hostUsageRecords.add(hostUsageRecord); } return hostUsageRecords; } private static List<org.openstack.atlas.service.domain.pojos.HostUsage> processDailyHostUsageMap(Map<Calendar, List<HostUsage>> dailyHostUsageMap) { List<org.openstack.atlas.service.domain.pojos.HostUsage> dailyHostUsageList = new ArrayList<org.openstack.atlas.service.domain.pojos.HostUsage>(); HostUsage lastUsageOfPreviousDay = null; if (dailyHostUsageMap == null) return dailyHostUsageList; for (Calendar day : dailyHostUsageMap.keySet()) { org.openstack.atlas.service.domain.pojos.HostUsage dailyHostUsage = new org.openstack.atlas.service.domain.pojos.HostUsage(); final List<HostUsage> hostUsageListForDay = dailyHostUsageMap.get(day); dailyHostUsage.setDay(day); dailyHostUsage.setBandwidthIn(processBandwidthIn(hostUsageListForDay, lastUsageOfPreviousDay)); dailyHostUsage.setBandwidthOut(processBandwidthOut(hostUsageListForDay, lastUsageOfPreviousDay)); dailyHostUsageList.add(dailyHostUsage); lastUsageOfPreviousDay = hostUsageListForDay.get(hostUsageListForDay.size() - 1); // Need this record so we don't lose 5 mins of info } return dailyHostUsageList; } /* * NOTE: This method assumes that the usage records are sorted by ascending snapshot time */ private static Long processBandwidthIn(List<HostUsage> hostUsages, HostUsage tagOnRecord) { Long cumulativeBytes = 0l; Long currentBytesSnapshot = null; Long lastBytesSnapshot = null; if (tagOnRecord != null) { lastBytesSnapshot = tagOnRecord.getBandwidthBytesIn(); } for (HostUsage hostUsage : hostUsages) { currentBytesSnapshot = hostUsage.getBandwidthBytesIn(); if (lastBytesSnapshot != null) { long delta = currentBytesSnapshot - lastBytesSnapshot; if (delta >= 0l) { cumulativeBytes += delta; } else if (Math.abs(delta) >= ZEUS_RESET_THRESHOLD_BYTES) { // Zeus's counter reset. cumulativeBytes += currentBytesSnapshot; } } lastBytesSnapshot = currentBytesSnapshot; } return cumulativeBytes; } /* * NOTE: This method assumes that the usage records are sorted by ascending snapshot time */ private static Long processBandwidthOut(List<HostUsage> hostUsages, HostUsage tagOnRecord) { Long cumulativeBytes = 0l; Long currentBytesSnapshot = null; Long lastBytesSnapshot = null; if (tagOnRecord != null) { lastBytesSnapshot = tagOnRecord.getBandwidthBytesOut(); } for (HostUsage hostUsage : hostUsages) { currentBytesSnapshot = hostUsage.getBandwidthBytesOut(); if (lastBytesSnapshot != null) { long delta = currentBytesSnapshot - lastBytesSnapshot; if (delta >= 0l) { cumulativeBytes += delta; } else if (Math.abs(delta) >= ZEUS_RESET_THRESHOLD_BYTES) { // Zeus's counter reset. cumulativeBytes += currentBytesSnapshot; } } lastBytesSnapshot = currentBytesSnapshot; } return cumulativeBytes; } /* * Returns a map with hostId ==> (day ==> List<HostUsage>). This method assumes that the usage * records are sorted by ascending snapshot time */ private static Map<Integer, Map<Calendar, List<HostUsage>>> convertRawUsageToMap(List<HostUsage> rawHostUsage) { Map<Integer, Map<Calendar, List<HostUsage>>> dailyHostUsageMap = new HashMap<Integer, Map<Calendar, List<HostUsage>>>(); if (rawHostUsage == null) return dailyHostUsageMap; for (HostUsage hostUsage : rawHostUsage) { Integer hostKey = hostUsage.getHostId(); if (!dailyHostUsageMap.containsKey(hostKey)) { Map<Calendar, List<HostUsage>> mapForHost = new TreeMap<Calendar, List<HostUsage>>(); dailyHostUsageMap.put(hostKey, mapForHost); } Calendar calKey = CalendarHelper.zeroOutTime(hostUsage.getSnapshotTime()); Map<Calendar, List<HostUsage>> mapForHost = dailyHostUsageMap.get(hostUsage.getHostId()); if (!mapForHost.containsKey(calKey)) { List<HostUsage> dailyHostUsageList = new ArrayList<HostUsage>(); mapForHost.put(calKey, dailyHostUsageList); } mapForHost.get(calKey).add(hostUsage); } return dailyHostUsageMap; } }