From 0c452e24344b21616ccd29f8bb2c437b5df96d19 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Wed, 4 Dec 2013 14:50:04 -0600 Subject: [PATCH] Issue #2545 - Get bandwidth graph data by network Change-Id: I4de455a4da43f180ff37eb72370addec77a29314 Former-commit-id: 9102f16c8a6409e92ded498b82a6a4e6a531f2c0 --- .../bandwidth/ui/AbstractCanvasImage.java | 14 +- .../bandwidth/ui/BandwidthCanvasComp.java | 8 +- .../datadelivery/bandwidth/ui/GraphImage.java | 33 +- .../data/BandwidthBucketDescription.java | 46 ++- .../bandwidth/data/BandwidthGraphData.java | 322 +++++++++--------- .../data/SubscriptionWindowData.java | 242 +++++++++++++ .../bandwidth/data/TimeWindowData.java | 70 ++-- .../bandwidth/BandwidthGraphDataAdapter.java | 115 ++++--- .../bandwidth/WfoBandwidthManagerCreator.java | 25 +- .../retrieval/BandwidthReservation.java | 23 +- .../bandwidth/retrieval/RetrievalPlan.java | 45 +-- .../bandwidth/util/BandwidthDaoUtil.java | 57 ++-- .../bandwidth/BandwidthServiceIntTest.java | 34 +- .../BandwidthGraphDataAdapterTest.java | 173 ++++++++++ 14 files changed, 875 insertions(+), 332 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/SubscriptionWindowData.java create mode 100644 tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapterTest.java diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/AbstractCanvasImage.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/AbstractCanvasImage.java index 6db5f31c2e..853fa628d8 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/AbstractCanvasImage.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/AbstractCanvasImage.java @@ -44,7 +44,8 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 28, 2012 1269 lvenable Initial creation. - * Dec 13, 2012 1269 lvenable Fixes and updates. + * Dec 13, 2012 1269 lvenable Fixes and updates. + * Nov 25, 2013 2545 mpduff Data sorted by network. * * * @@ -213,18 +214,19 @@ public abstract class AbstractCanvasImage { switch (imageMgr.getSortBy()) { case NAME_ASC: - return graphData.getSortedNames(true); + return graphData.getSortedNames(true, imageMgr.getNetwork()); case NAME_DESC: - return graphData.getSortedNames(false); + return graphData.getSortedNames(false, imageMgr.getNetwork()); case CURRENT_TIME: return graphData.getSubscriptionsSortedByTime( - imageMgr.getCurrentTimeMillis(), true); + imageMgr.getNetwork(), imageMgr.getCurrentTimeMillis(), + true); case SELECTED_INTERSECT: return graphData.getSubscriptionsSortedByTime( - imageMgr.getSortTimeMillis(), true); + imageMgr.getNetwork(), imageMgr.getSortTimeMillis(), true); case SELECTED_START: return graphData.getSubscriptionsSortedByTime( - imageMgr.getSortTimeMillis(), false); + imageMgr.getNetwork(), imageMgr.getSortTimeMillis(), false); default: return new ArrayList(); } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java index 123b949454..9db73f1013 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java @@ -101,6 +101,7 @@ import com.raytheon.uf.viz.datadelivery.utils.DataDeliveryUtils; * Jan 28, 2013 1529 djohnson Disable menu items if no subscriptions selected. * Oct 28, 2013 2430 mpduff Add % of bandwidth utilized graph. * Nov 19, 2013 1531 mpduff Made graph resizable. + * Nov 25, 2013 2545 mpduff Default to Opsnet if Network not available yet. * * * @author lvenable @@ -445,7 +446,12 @@ public class BandwidthCanvasComp extends Composite implements IDialogClosed, int totalHeight = 0; if (bgd != null) { - numOfSubs = bgd.getNumberOfSubscriptions(); + if (imageMgr == null) { + // Default to OPSNET + numOfSubs = bgd.getNumberOfSubscriptions(Network.OPSNET); + } else { + numOfSubs = bgd.getNumberOfSubscriptions(imageMgr.getNetwork()); + } totalHeight = AbstractCanvasImage.TEXT_OFFSET * numOfSubs; } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/GraphImage.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/GraphImage.java index a9867fa198..3b32abf3b5 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/GraphImage.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/GraphImage.java @@ -34,6 +34,7 @@ import org.eclipse.swt.widgets.Composite; import com.raytheon.uf.common.datadelivery.bandwidth.data.BandwidthGraphData; import com.raytheon.uf.common.datadelivery.bandwidth.data.TimeWindowData; +import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionPriority; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.viz.datadelivery.bandwidth.ui.BandwidthImageMgr.SortBy; @@ -53,6 +54,7 @@ import com.raytheon.uf.viz.datadelivery.bandwidth.ui.BandwidthImageMgr.SortBy; * Jan 04, 2013 1420 mpduff Change default priority to normal priority. * Jan 25, 2013 1528 djohnson Subscription priority is now an enum, remove incorrect use of ordinal values. * Oct 28, 2013 2430 mpduff Add % of bandwidth utilized graph. + * Nov 25, 2013 2545 mpduff Data organized by network. * * * @@ -154,6 +156,10 @@ public class GraphImage extends AbstractCanvasImage { * Graphics Context */ private void drawData(GC gc) { + if (graphData == null) { + return; + } + windowTimeInfoMap.clear(); int offset = 22; @@ -161,30 +167,26 @@ public class GraphImage extends AbstractCanvasImage { Color c = null; gc.setForeground(display.getSystemColor(SWT.COLOR_GRAY)); - if (graphData == null) { - return; - } + Network network = imageMgr.getNetwork(); long currentTimeMillis = imageMgr.getCurrentTimeMillis(); // Loop over data and draw - Map> dataMap = graphData.getDataMap(); - List subscriptionList = getSortedData(); for (String subName : subscriptionList) { if (imageMgr.isColorByPriority()) { - if (graphData.getPriority(subName) == SubscriptionPriority.NORMAL) { + if (graphData.getPriority(network, subName) == SubscriptionPriority.NORMAL) { c = new Color( display, imageMgr.getPriorityColor(SubscriptionPriority.NORMAL)); gc.setBackground(c); - } else if (graphData.getPriority(subName) == SubscriptionPriority.HIGH) { + } else if (graphData.getPriority(network, subName) == SubscriptionPriority.HIGH) { c = new Color( display, imageMgr.getPriorityColor(SubscriptionPriority.HIGH)); gc.setBackground(c); - } else if (graphData.getPriority(subName) == SubscriptionPriority.LOW) { + } else if (graphData.getPriority(network, subName) == SubscriptionPriority.LOW) { c = new Color(display, imageMgr.getPriorityColor(SubscriptionPriority.LOW)); gc.setBackground(c); @@ -204,7 +206,8 @@ public class GraphImage extends AbstractCanvasImage { } long startTime = 0; - List timeWindows = dataMap.get(subName); + List timeWindows = graphData.getTimeWindowArray( + imageMgr.getNetwork(), subName); for (TimeWindowData data : timeWindows) { startTime = data.getTimeWindowStartTime(); if (data.getTimeWindowEndTime() < currentTimeMillis) { @@ -221,7 +224,8 @@ public class GraphImage extends AbstractCanvasImage { int xCoord2 = 0; long endTime = data.getTimeWindowEndTime(); if (endTime == startTime) { - endTime = startTime + graphData.getBinTimeInMins() + endTime = startTime + + graphData.getBinTimeInMinutes(network) * TimeUtil.MILLIS_PER_MINUTE; } @@ -324,7 +328,6 @@ public class GraphImage extends AbstractCanvasImage { return; } - Map> dataMap = graphData.getDataMap(); long startTime = 0; long currentTimeMillis = imageMgr.getCurrentTimeMillis(); List subscriptionList = getSortedData(); @@ -332,7 +335,8 @@ public class GraphImage extends AbstractCanvasImage { int yCoord = cs.getImageHeight() - offset; for (String subName : subscriptionList) { - List timeWindows = dataMap.get(subName); + List timeWindows = graphData.getTimeWindowArray( + imageMgr.getNetwork(), subName); for (TimeWindowData data : timeWindows) { startTime = data.getTimeWindowStartTime(); if (data.getTimeWindowEndTime() < currentTimeMillis) { @@ -349,8 +353,9 @@ public class GraphImage extends AbstractCanvasImage { int xCoord2 = 0; long endTime = data.getTimeWindowEndTime(); if (endTime == startTime) { - endTime = startTime + graphData.getBinTimeInMins() - * TimeUtil.MILLIS_PER_MINUTE; + endTime = startTime + + graphData.getBinTimeInMinutes(imageMgr + .getNetwork()) * TimeUtil.MILLIS_PER_MINUTE; } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthBucketDescription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthBucketDescription.java index 279b0be83b..0741b0856d 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthBucketDescription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthBucketDescription.java @@ -34,7 +34,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Sep 20, 2013 2397 bgonzale Initial creation + * Sep 20, 2013 2397 bgonzale Initial creation. + * Nov 25, 2545 2545 mpduff Added bucketTimeInMinutes. * * * @@ -60,6 +61,9 @@ public class BandwidthBucketDescription implements @DynamicSerializeElement private long bucketStartTime; + @DynamicSerializeElement + private int bucketTimeMinutes; + /** * Default Constructor. */ @@ -154,4 +158,44 @@ public class BandwidthBucketDescription implements this.bucketStartTime = bucketStartTime; } + /** + * @return the bucketTimeMinutes + */ + public int getBucketTimeMinutes() { + return bucketTimeMinutes; + } + + /** + * @param bucketTimeMinutes + * the bucketTimeMinutes to set + */ + public void setBucketTimeMinutes(int bucketTimeMinutes) { + this.bucketTimeMinutes = bucketTimeMinutes; + } + + /** + * Get any data that is leftover after filling the bucket. + * + * @return The amount of data overage + */ + public long getLeftovers() { + long leftover = 0; + + if (this.usedBytes > this.bucketSize) { + leftover = usedBytes - bucketSize; + usedBytes = bucketSize; + } + + return leftover; + } + + /** + * Add any leftovers from the previous buckets. + * + * @param leftovers + * data overage from previous buckets + */ + public void addLeftovers(long leftovers) { + this.usedBytes += leftovers; + } } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java index 84a45b53d3..fe9f5d242c 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; @@ -49,6 +50,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Jan 25, 2013 1528 djohnson Subscription priority is now an enum. * Sep 20, 2013 2397 bgonzale Added Map of Bucket Descriptions. * Nov 19, 2013 2545 bgonzale Added 'add' method stub. Still work to do. + * Nov 25, 2013 2545 mpduff Finished implementing 2545. * * * @@ -57,84 +59,34 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; */ @DynamicSerialize public class BandwidthGraphData { - /** Subscription Name -> TimeWindowData list */ + /** Network -> List of SubscriptionWindowData */ @DynamicSerializeElement - private Map> dataMap; - - /** Subscription Name -> Subscription Priority */ - @DynamicSerializeElement - private Map priorityMap; + private Map> networkDataMap; /** Network -> Bandwidth Bucket Descriptions */ @DynamicSerializeElement private Map> networkBucketMap; - /** Bin duration in minutes */ - @DynamicSerializeElement - private int binTimeInMins; - /** * Constructor. - * - * @deprecated Required by dynamic serialization, use - * {@link #BandwidthGraphData(int)} instead. */ - @Deprecated public BandwidthGraphData() { - this(3); + networkDataMap = new HashMap>(2); + networkBucketMap = new HashMap>( + 2); } /** - * Constructor. - * - * @param binTimeMins - * bin duration in minutes - */ - public BandwidthGraphData(int binTimeMins) { - this.binTimeInMins = binTimeMins; - dataMap = new HashMap>(); - priorityMap = new HashMap(); - } - - /** - * Add the other BandwidthGraphData data to this object. + * Save the bucket descriptions. * - * @param other + * @param network + * The network the buckets belong to + * @param buckets + * The buckets to save */ - public void add(BandwidthGraphData other) { - /* - * TODO merge SBN and OPSNET data into on Bandwidth Graph Data - */ - } - - /** - * @return the dataMap - */ - public Map> getDataMap() { - return dataMap; - } - - /** - * @param dataMap - * the dataMap to set - */ - public void setDataMap(Map> dataMap) { - this.dataMap = dataMap; - } - - /** - * @return the priorityMap - */ - public Map getPriorityMap() { - return priorityMap; - } - - /** - * @param priorityMap - * the priorityMap to set - */ - public void setPriorityMap(Map priorityMap) { - this.priorityMap = priorityMap; + public void addBucketDescriptions(Network network, + SortedSet buckets) { + networkBucketMap.put(network, buckets); } /** @@ -160,135 +112,133 @@ public class BandwidthGraphData { this.networkBucketMap = new HashMap>(); for (Entry> descEntry : networkBucketMap .entrySet()) { - this.networkBucketMap.put(descEntry.getKey(), + this.networkBucketMap.put( + descEntry.getKey(), new TreeSet( (Collection) descEntry - .getValue())); + .getValue())); } } - /** - * @return the binTimeInMins - */ - public int getBinTimeInMins() { - return binTimeInMins; - } - - /** - * @param binTimeInMins - * the binTimeInMins to set - */ - public void setBinTimeInMins(int binTimeInMins) { - this.binTimeInMins = binTimeInMins; - } - - /** - * Get the bin time in minutes - * - * @return bin time - */ - public int getBinTimeInMinutes() { - return binTimeInMins; - } - - /** - * Add a Graph Data Array. - * - * @param subscriptionName - * @param priority - * @param dataArray - */ - public void addGraphDataArray(String subscriptionName, - SubscriptionPriority priority, - List dataArray) { - dataMap.put(subscriptionName, dataArray); - priorityMap.put(subscriptionName, priority); - } - /** * Get the sorted names. - * + * * @param ascending * sort in ascending or descending, true for ascending + * @param network + * The network type requested * @return List of names */ - public List getSortedNames(boolean ascending) { - ArrayList keyArray = new ArrayList(); - - for (String s : dataMap.keySet()) { - keyArray.add(s); + public List getSortedNames(boolean ascending, Network network) { + List subList = this.networkDataMap.get(network); + List subNameList = new ArrayList(subList.size()); + for (SubscriptionWindowData s : subList) { + subNameList.add(s.getSubscriptionName()); } - Collections.sort(keyArray); - /* * Since the data will be drawn from the bottom up, ascending is * actually reverse order of the sort. */ if (ascending) { - Collections.reverse(keyArray); + Collections.reverse(subNameList); + } else { + Collections.sort(subNameList); } - return keyArray; + return subNameList; } /** * Sort the graph data */ public void sortGraphData() { - for (Entry> entry : dataMap.entrySet()) { - Collections.sort(entry.getValue()); + for (Entry> entry : networkDataMap + .entrySet()) { + for (SubscriptionWindowData swd : entry.getValue()) { + Collections.sort(swd.getWindowDataList()); + } } } /** * Get the time window array for the subscription - * + * + * @param network + * The Network + * * @param subName * Subscription name - * + * * @return List of TimeWindowData objects */ - public List getTimeWindowArray(String subName) { - return dataMap.get(subName); + public List getTimeWindowArray(Network network, + String subName) { + for (Entry> entry : networkDataMap + .entrySet()) { + for (SubscriptionWindowData swd : entry.getValue()) { + if (swd.getSubscriptionName().equals(subName)) { + return swd.getWindowDataList(); + } + } + } + + return new ArrayList(0); } /** * Get the priority for the subscription name. - * - * @param subscriptionName + * + * @param network + * The network to check for the subscription name + * + * @param subName * The subscription name. * @return The priority number. */ - public SubscriptionPriority getPriority(String subscriptionName) { - if (priorityMap.containsKey(subscriptionName)) { - return priorityMap.get(subscriptionName); + public SubscriptionPriority getPriority(Network network, String subName) { + for (Entry> entry : networkDataMap + .entrySet()) { + for (SubscriptionWindowData swd : entry.getValue()) { + if (swd.getSubscriptionName().equals(subName)) { + return swd.getPriority(); + } + } } // This should never occur. throw new IllegalArgumentException( - "Unable to find a priority for subscription [" - + subscriptionName + "]"); + "Unable to find a priority for subscription [" + subName + "]"); } /** * Get the number of subscriptions - * + * + * @param network + * The network to check + * * @return Number of subscriptions */ - public int getNumberOfSubscriptions() { - return dataMap.keySet().size(); + public int getNumberOfSubscriptions(Network network) { + return networkDataMap.get(network).size(); } /** * Get a list of subscription names that are sorted by the earliest time * window time. If two subscription share the same time window time then the * subscription names will be in alphabetical order. - * + * + * @param network + * The network + * @param currentTime + * The time + * @param intersect + * True if current time intesects the download window + * * @return List of subscription names. */ - public List getSubscriptionsSortedByTime(long currentTime, - boolean intersect) { + public List getSubscriptionsSortedByTime(Network network, + long currentTime, boolean intersect) { /* * Sort each of the subscriptions array time windows so they are in * order by time window start time. @@ -302,28 +252,27 @@ public class BandwidthGraphData { Map> sortedTimeMap = new TreeMap>(); long startTime = 0L; - for (Entry> entry : dataMap.entrySet()) { - if (!entry.getValue().isEmpty()) { - for (TimeWindowData data : entry.getValue()) { - if (intersect) { - if (data.getTimeWindowEndTime() > currentTime) { - startTime = data.getTimeWindowStartTime(); - break; - } - } else { - if (data.getTimeWindowStartTime() >= currentTime) { - startTime = data.getTimeWindowStartTime(); - break; - } + for (SubscriptionWindowData swd : networkDataMap.get(network)) { + for (TimeWindowData data : swd.getWindowDataList()) { + if (intersect) { + if (data.getTimeWindowEndTime() > currentTime) { + startTime = data.getTimeWindowStartTime(); + break; + } + } else { + if (data.getTimeWindowStartTime() >= currentTime) { + startTime = data.getTimeWindowStartTime(); + break; } } - if (sortedTimeMap.containsKey(startTime)) { - sortedTimeMap.get(startTime).add(entry.getKey()); - } else { - List tmpArray = new ArrayList(); - tmpArray.add(entry.getKey()); - sortedTimeMap.put(startTime, tmpArray); - } + } + + if (sortedTimeMap.containsKey(startTime)) { + sortedTimeMap.get(startTime).add(swd.getSubscriptionName()); + } else { + List tmpArray = new ArrayList(); + tmpArray.add(swd.getSubscriptionName()); + sortedTimeMap.put(startTime, tmpArray); } } @@ -341,4 +290,73 @@ public class BandwidthGraphData { return sortedSubscriptionNames; } + + /** + * Get a list of available networks + * + * @return List of available Networks + */ + public List getAvailableNetworks() { + List networkList = new ArrayList(3); + for (Network network : networkDataMap.keySet()) { + networkList.add(network.name()); + } + + return networkList; + } + + /** + * @return the networkDataMap + */ + public Map> getNetworkDataMap() { + return networkDataMap; + } + + /** + * @param networkDataMap + * the networkDataMap to set + */ + public void setNetworkDataMap( + Map> networkDataMap) { + this.networkDataMap = networkDataMap; + } + + /** + * Get the bin time in minutes. + * + * @param network + * The network to check + * @return The bin time in minutes + */ + public int getBinTimeInMinutes(Network network) { + Set bucketSet = this.networkBucketMap + .get(network); + return bucketSet.iterator().next().getBucketTimeMinutes(); + } + + /** + * Merge another Bandwidth graph data into this object. + * + * @param data2 + * The other data set to merge + */ + public void merge(BandwidthGraphData data2) { + Map> nbm = data2 + .getNetworkBucketMap(); + + for (Network network : nbm.keySet()) { + if (!networkBucketMap.containsKey(network)) { + networkBucketMap.put(network, nbm.get(network)); + } + } + + Map> ndm = data2 + .getNetworkDataMap(); + + for (Network network : ndm.keySet()) { + if (!networkDataMap.containsKey(network)) { + networkDataMap.put(network, ndm.get(network)); + } + } + } } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/SubscriptionWindowData.java b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/SubscriptionWindowData.java new file mode 100644 index 0000000000..626dacc160 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/SubscriptionWindowData.java @@ -0,0 +1,242 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.datadelivery.bandwidth.data; + +import java.util.ArrayList; +import java.util.List; + +import com.raytheon.uf.common.datadelivery.registry.Network; +import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionPriority; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Subscription object holding the download window information. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Nov 21, 2013   2545     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ +@DynamicSerialize +public class SubscriptionWindowData { + /** The network this subscription is associate with */ + @DynamicSerializeElement + private Network network; + + /** The registry id of the subscription */ + @DynamicSerializeElement + private String registryId; + + /** The subscription name */ + @DynamicSerializeElement + private String subscriptionName; + + /** The list of download window data */ + @DynamicSerializeElement + private List windowDataList; + + /** The subscription's priority */ + @DynamicSerializeElement + private SubscriptionPriority priority; + + /** + * Default Constructor. + */ + public SubscriptionWindowData() { + windowDataList = new ArrayList(); + } + + /** + * Constructor. + * + * @param subscriptionName + * The subscription's name + * @param windowsDataList + * The list of download window data + * @param priority + * The subscription's priority + */ + public SubscriptionWindowData(String subscriptionName, + List windowsDataList, SubscriptionPriority priority) { + this.subscriptionName = subscriptionName; + this.windowDataList = windowsDataList; + this.priority = priority; + } + + /** + * @return the subscriptionName + */ + public String getSubscriptionName() { + return subscriptionName; + } + + /** + * @param subscriptionName + * the subscriptionName to set + */ + public void setSubscriptionName(String subscriptionName) { + this.subscriptionName = subscriptionName; + } + + /** + * @return the windowDataList + */ + public List getWindowDataList() { + return windowDataList; + } + + /** + * @param windowDataList + * the windowDataList to set + */ + public void setWindowDataList(List windowDataList) { + this.windowDataList = windowDataList; + } + + /** + * Add a TimeWindowData object + */ + public void addTimeWindow(TimeWindowData windowData) { + this.windowDataList.add(windowData); + } + + /** + * @return the priority + */ + public SubscriptionPriority getPriority() { + return priority; + } + + /** + * @param priority + * the priority to set + */ + public void setPriority(SubscriptionPriority priority) { + this.priority = priority; + } + + /** + * @return the network + */ + public Network getNetwork() { + return network; + } + + /** + * @param network + * the network to set + */ + public void setNetwork(Network network) { + this.network = network; + } + + /** + * @return the registryId + */ + public String getRegistryId() { + return registryId; + } + + /** + * @param registryId + * the registryId to set + */ + public void setRegistryId(String registryId) { + this.registryId = registryId; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((network == null) ? 0 : network.hashCode()); + result = prime * result + + ((priority == null) ? 0 : priority.hashCode()); + result = prime * result + + ((registryId == null) ? 0 : registryId.hashCode()); + result = prime + * result + + ((subscriptionName == null) ? 0 : subscriptionName.hashCode()); + result = prime * result + + ((windowDataList == null) ? 0 : windowDataList.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SubscriptionWindowData)) { + return false; + } + SubscriptionWindowData other = (SubscriptionWindowData) obj; + if (network != other.network) { + return false; + } + if (priority != other.priority) { + return false; + } + if (registryId == null) { + if (other.registryId != null) { + return false; + } + } else if (!registryId.equals(other.registryId)) { + return false; + } + if (subscriptionName == null) { + if (other.subscriptionName != null) { + return false; + } + } else if (!subscriptionName.equals(other.subscriptionName)) { + return false; + } + if (windowDataList == null) { + if (other.windowDataList != null) { + return false; + } + } else if (!windowDataList.equals(other.windowDataList)) { + return false; + } + return true; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/TimeWindowData.java b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/TimeWindowData.java index fc1cfa56df..594edbd85b 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/TimeWindowData.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/TimeWindowData.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.List; import java.util.TimeZone; +import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.time.util.TimeUtil; @@ -42,6 +43,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Nov 25, 2012 1269 lvenable Initial creation. * Dec 06, 2012 1397 djohnson Add dynamic serialize class annotation. * Jan 07, 2013 1451 djohnson Use TimeUtil.newGmtCalendar(). + * Nov 25, 2013 2545 mpduff Add Network. * * * @@ -62,6 +64,10 @@ public class TimeWindowData implements Comparable { @DynamicSerializeElement private List binStartTimes; + /** The network for the data */ + @DynamicSerializeElement + private Network network; + /** * Constructor. * @@ -75,7 +81,7 @@ public class TimeWindowData implements Comparable { /** * Constructor - * + * * @param windowStartTime * Latency start time in milliseconds. * @param windowEndTime @@ -88,50 +94,47 @@ public class TimeWindowData implements Comparable { * already be at the minute so this maybe redundant but we need to * remove the seconds and millisecond to graph properly. */ - this.timeWindowStartTime = (windowStartTime / TimeUtil.MILLIS_PER_MINUTE) * TimeUtil.MILLIS_PER_MINUTE; - this.timeWindowEndTime = (windowEndTime / TimeUtil.MILLIS_PER_MINUTE) * TimeUtil.MILLIS_PER_MINUTE; - - init(); - } - - /** - * Initialize. - */ - private void init() { + this.timeWindowStartTime = (windowStartTime / TimeUtil.MILLIS_PER_MINUTE) + * TimeUtil.MILLIS_PER_MINUTE; + this.timeWindowEndTime = (windowEndTime / TimeUtil.MILLIS_PER_MINUTE) + * TimeUtil.MILLIS_PER_MINUTE; binStartTimes = new ArrayList(); } /** * Set the bin times. - * + * * @param binTimesArray */ public void setBinTimes(List binTimesArray) { binStartTimes = binTimesArray; - Collections.sort(binStartTimes); + sortBinStartTimes(); } /** * Add a bin time. - * + * * @param binStartTime */ public void addBinTime(Long binStartTime) { if (validBinStartTime(binStartTime)) { - long roundedBinTime = (binStartTime / TimeUtil.MILLIS_PER_MINUTE) * TimeUtil.MILLIS_PER_MINUTE; + long roundedBinTime = (binStartTime / TimeUtil.MILLIS_PER_MINUTE) + * TimeUtil.MILLIS_PER_MINUTE; binStartTimes.add(roundedBinTime); + sortBinStartTimes(); return; } } /** * Validate the bin time. - * + * * @param binStartTime * @return true if bin time is within the time window */ private boolean validBinStartTime(Long binStartTime) { - return binStartTime >= timeWindowStartTime && binStartTime <= timeWindowEndTime; + return binStartTime >= timeWindowStartTime + && binStartTime <= timeWindowEndTime; } /** @@ -157,7 +160,7 @@ public class TimeWindowData implements Comparable { /** * Get the time window start time. - * + * * @return */ public long getTimeWindowStartTime() { @@ -166,7 +169,7 @@ public class TimeWindowData implements Comparable { /** * Get the time window end time. - * + * * @return */ public long getTimeWindowEndTime() { @@ -175,7 +178,7 @@ public class TimeWindowData implements Comparable { /** * Get the time window end time. - * + * * @return */ public List getBinStartTimes() { @@ -183,26 +186,44 @@ public class TimeWindowData implements Comparable { } /** - * @param timeWindowStartTime the timeWindowStartTime to set + * @param timeWindowStartTime + * the timeWindowStartTime to set */ public void setTimeWindowStartTime(long timeWindowStartTime) { this.timeWindowStartTime = timeWindowStartTime; } /** - * @param timeWindowEndTime the timeWindowEndTime to set + * @param timeWindowEndTime + * the timeWindowEndTime to set */ public void setTimeWindowEndTime(long timeWindowEndTime) { this.timeWindowEndTime = timeWindowEndTime; } /** - * @param binStartTimes the binStartTimes to set + * @param binStartTimes + * the binStartTimes to set */ public void setBinStartTimes(List binStartTimes) { this.binStartTimes = binStartTimes; } + /** + * @return the network + */ + public Network getNetwork() { + return network; + } + + /** + * @param network + * the network to set + */ + public void setNetwork(Network network) { + this.network = network; + } + /** * {@inheritDoc} */ @@ -214,7 +235,8 @@ public class TimeWindowData implements Comparable { cal.setTimeInMillis(this.timeWindowStartTime); StringBuilder sb = new StringBuilder(); - sb.append("Start Time:\t").append(sdf.format(cal.getTime())).append(" Z"); + sb.append("Start Time:\t").append(sdf.format(cal.getTime())) + .append(" Z"); sb.append("\n"); cal.setTimeInMillis(this.timeWindowEndTime); sb.append("End Time:\t").append(sdf.format(cal.getTime())).append(" Z"); diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapter.java index 3cd7844b21..17cdbe5fea 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapter.java @@ -24,14 +24,13 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.SortedSet; import java.util.TreeSet; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; +import com.google.common.annotations.VisibleForTesting; import com.raytheon.uf.common.datadelivery.bandwidth.data.BandwidthBucketDescription; import com.raytheon.uf.common.datadelivery.bandwidth.data.BandwidthGraphData; +import com.raytheon.uf.common.datadelivery.bandwidth.data.SubscriptionWindowData; import com.raytheon.uf.common.datadelivery.bandwidth.data.TimeWindowData; import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionPriority; @@ -61,6 +60,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalPlan; * Jun 24, 2013 2106 djohnson Access bucket allocations through RetrievalPlan. * Jul 11, 2013 2106 djohnson Use priority straight from the BandwidthSubscription. * Sep 20, 2013 2397 bgonzale Add Map of Bucket Descriptions to BandwidthGraphData. + * Nov 27, 2013 2545 mpduff Get data by network * * * @@ -79,8 +79,6 @@ class BandwidthGraphDataAdapter { * * @param retrievalManager * the bucket time in minutes - * @param bandwidthDao - * the bandwidth dao */ public BandwidthGraphDataAdapter(RetrievalManager retrievalManager) { this.retrievalManager = retrievalManager; @@ -92,37 +90,33 @@ class BandwidthGraphDataAdapter { * @return the data */ public BandwidthGraphData get() { - // Technically this is wrong, because different Networks can have - // different bucket minutes. The BandwidthGraphData object should be - // changed later to reflect this - final BandwidthGraphData bandwidthGraphData = new BandwidthGraphData( - retrievalManager.getRetrievalPlans().values().iterator().next() - .getBucketMinutes()); - - Map> dataMap = new HashMap>(); - Map priorityMap = new HashMap(); - - Map retrievals = new HashMap(); - Multimap reservations = ArrayListMultimap - .create(); - Multimap subNameToRetrievals = ArrayListMultimap - .create(); - Map> networkBucketMap = new HashMap>(); + final BandwidthGraphData bandwidthGraphData = new BandwidthGraphData(); Collection retrievalPlans = retrievalManager .getRetrievalPlans().values(); + Map retrievals = new HashMap(); + Map> reservations = new HashMap>(); + Map> networkMap = new HashMap>(); + + // One retrieval plan per network for (RetrievalPlan retrievalPlan : retrievalPlans) { + Network network = retrievalPlan.getNetwork(); + if (!networkMap.containsKey(network)) { + networkMap + .put(network, new ArrayList()); + } + // Get all buckets that are in the retrieval plan from the current // time forward final SortedSet bandwidthBuckets = retrievalPlan .getBucketsInWindow(TimeUtil.currentTimeMillis(), Long.MAX_VALUE); - networkBucketMap.put(retrievalPlan.getNetwork(), - toDescriptions(bandwidthBuckets)); - // Add all subscription retrievals to a collection keyed by sub - // name, and associate all of the bandwidth reservations with their - // associated retrievals + // % utilized graph data + SortedSet buckets = toDescriptions(bandwidthBuckets); + bandwidthGraphData.addBucketDescriptions(network, buckets); + + // Latency window data - accumulate all the reservations for (BandwidthBucket bucket : bandwidthBuckets) { final List requests = retrievalPlan .getBandwidthAllocationsForBucket(bucket); @@ -130,9 +124,6 @@ class BandwidthGraphDataAdapter { if (allocation instanceof SubscriptionRetrieval) { final SubscriptionRetrieval subRetrieval = (SubscriptionRetrieval) allocation; retrievals.put(allocation.getId(), subRetrieval); - subNameToRetrievals.put(subRetrieval - .getBandwidthSubscription().getName(), - subRetrieval); } } @@ -140,61 +131,83 @@ class BandwidthGraphDataAdapter { .getBandwidthReservationsForBucket(bucket); for (BandwidthReservation reservation : bandwidthReservations) { - reservations.put(reservation.getId(), reservation); + if (!reservations.containsKey(reservation.getId())) { + reservations.put(reservation.getId(), + new ArrayList()); + } + reservations.get(reservation.getId()).add(reservation); } } } // Create time windows for each subscription retrieval by aggregating - // them with an reservations they have - for (Entry entry : retrievals.entrySet()) { - final SubscriptionRetrieval value = entry.getValue(); - BandwidthSubscription dao = value.getBandwidthSubscription(); - final String subName = dao.getName(); - priorityMap.put(subName, dao.getPriority()); + // them with any reservations they have + for (Long key : retrievals.keySet()) { + final SubscriptionRetrieval retrieval = retrievals.get(key); + BandwidthSubscription dao = retrieval.getBandwidthSubscription(); + String subName = dao.getName(); + SubscriptionPriority priority = dao.getPriority(); + String registryId = retrieval.getBandwidthSubscription() + .getRegistryId(); + Network network = retrieval.getNetwork(); - List timeWindows = dataMap.get(subName); + SubscriptionWindowData windowData = null; - if (timeWindows == null) { - timeWindows = new ArrayList(); - dataMap.put(subName, timeWindows); + List subList = networkMap.get(network); + for (SubscriptionWindowData subData : subList) { + if (subData.getRegistryId().equals(registryId)) { + windowData = subData; + break; + } } - final long startMillis = value.getStartTime().getTimeInMillis(); + if (windowData == null) { + windowData = new SubscriptionWindowData(); + windowData.setNetwork(network); + windowData.setPriority(priority); + windowData.setRegistryId(registryId); + windowData.setSubscriptionName(subName); + networkMap.get(network).add(windowData); + } + + final long startMillis = retrieval.getStartTime().getTimeInMillis(); final long endMillis = startMillis - + (value.getSubscriptionLatency() * TimeUtil.MILLIS_PER_MINUTE); + + (retrieval.getSubscriptionLatency() * TimeUtil.MILLIS_PER_MINUTE); TimeWindowData window = new TimeWindowData(startMillis, endMillis); List binStartTimes = new ArrayList(); - binStartTimes.add(value.getStartTime().getTimeInMillis()); - for (BandwidthReservation reservation : reservations.get(value + binStartTimes.add(retrieval.getStartTime().getTimeInMillis()); + for (BandwidthReservation reservation : reservations.get(retrieval .getIdentifier())) { binStartTimes.add(reservation.getBandwidthBucket()); } window.setBinStartTimes(binStartTimes); - timeWindows.add(window); + windowData.addTimeWindow(window); } - bandwidthGraphData.setDataMap(dataMap); - bandwidthGraphData.setPriorityMap(priorityMap); - bandwidthGraphData.setNetworkBucketMap(networkBucketMap); + bandwidthGraphData.setNetworkDataMap(networkMap); return bandwidthGraphData; } - /* + /** * Return BandwithBucketDescription objects for the given BandwidthBuckets. */ - private SortedSet toDescriptions( + @VisibleForTesting + SortedSet toDescriptions( SortedSet bandwidthBuckets) { SortedSet descriptions = new TreeSet(); + long leftovers = 0; for (BandwidthBucket bucket : bandwidthBuckets) { BandwidthBucketDescription desc = new BandwidthBucketDescription( bucket.getNetwork(), bucket.getBucketSize(), bucket.getCurrentSize(), bucket.getBucketStartTime()); + desc.addLeftovers(leftovers); + + leftovers = desc.getLeftovers(); descriptions.add(desc); } + return descriptions; } - } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java index 9f190144c5..f7e0d79c00 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java @@ -64,18 +64,21 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Nov 19, 2013 2545 bgonzale Added registryEventListener method for update events. * Added getBandwidthGraphData. * Reschedule updated local subscriptions. + * Nov 27, 2013 2545 mpduff Get data by network * * * * @author djohnson * @version 1.0 */ -public class WfoBandwidthManagerCreator implements IEdexBandwidthManagerCreator { +public class WfoBandwidthManagerCreator + implements IEdexBandwidthManagerCreator { /** * WFO {@link BandwidthManager} implementation. */ - static class WfoBandwidthManager extends EdexBandwidthManager { + static class WfoBandwidthManager + extends EdexBandwidthManager { private static final String[] WFO_BANDWIDTH_MANAGER_FILES = new String[] { JarUtil.getResResourcePath("/spring/bandwidth-datadelivery-wfo-edex-impl.xml"), @@ -125,8 +128,7 @@ public class WfoBandwidthManagerCreator impl Subscription subscription = getRegistryObjectById( getSubscriptionHandler(), event.getId()); boolean isLocalOrigination = subscription.getOriginatingSite() - .equals( - SiteUtil.getSite()); + .equals(SiteUtil.getSite()); if (isLocalOrigination) { subscriptionUpdated(subscription); @@ -164,18 +166,26 @@ public class WfoBandwidthManagerCreator impl */ @Override protected Set scheduleSbnSubscriptions( - List> subscriptions) throws SerializationException { + List> subscriptions) + throws SerializationException { return ncfBandwidthService.schedule(subscriptions); } + /** + * {@inheritDoc} + */ @Override protected BandwidthGraphData getBandwidthGraphData() { BandwidthGraphData data = super.getBandwidthGraphData(); - data.add(ncfBandwidthService.getBandwidthGraphData()); + BandwidthGraphData data2 = ncfBandwidthService + .getBandwidthGraphData(); + if (data2 != null) { + data.merge(data2); + } + return data; } - } /** @@ -192,5 +202,4 @@ public class WfoBandwidthManagerCreator impl retrievalManager, bandwidthDaoUtil, dataSetMetaDataHandler, subscriptionHandler, subscriptionNotificationService); } - } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/BandwidthReservation.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/BandwidthReservation.java index d9e2ea0781..95896d9fee 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/BandwidthReservation.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/BandwidthReservation.java @@ -23,7 +23,8 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Nov 09, 2012 1286 djohnson Add getters for bytes. * Jun 24, 2013 2106 djohnson Add copy constructor. * Jul 11, 2013 2106 djohnson Use SubscriptionPriority enum. - * Oct 30, 2013 2448 dhladky Moved methods to TimeUtil. + * Oct 30, 2013 2448 dhladky Moved methods to TimeUtil. + * Dec 02, 2013 2545 mpduff Set size in bytes. * * * @@ -41,6 +42,7 @@ public class BandwidthReservation implements Serializable, private SubscriptionPriority priority; + /** Size of the reservation in bytes */ private long size; private final RetrievalStatus status = RetrievalStatus.RESERVED; @@ -65,8 +67,8 @@ public class BandwidthReservation implements Serializable, * BandwidthReservation. * * @param bandwidthRequired - * The amount of bandwidth this BandwidthReservation should - * reserve in a {@link RetrievalPlan}. + * The amount of bandwidth in bytes this BandwidthReservation + * should reserve in a {@link RetrievalPlan}. */ public BandwidthReservation(BandwidthAllocation allocation, long bandwidthRequired) { @@ -101,7 +103,7 @@ public class BandwidthReservation implements Serializable, sb.append("reserve id: [").append(getId()).append("] "); sb.append("path [").append(getNetwork()).append("] "); sb.append("priority [").append(getPriority()).append("] "); - sb.append("size (bytes) [").append(getSizeInBytes()).append("] "); + sb.append("size (bytes) [").append(getSize()).append("] "); sb.append("status [").append(getStatus()).append("] "); sb.append("startTime [").append(BandwidthUtil.format(getStartTime())) .append("] "); @@ -141,27 +143,20 @@ public class BandwidthReservation implements Serializable, } /** - * @param estimatedSize - * the estimatedSize to set, in kilobytes + * @param size + * the estimatedSize to set, in bytes */ public void setSize(long size) { this.size = size; } /** - * @return the estimatedSize, in kilobytes + * @return the estimatedSize, in bytes */ public long getSize() { return size; } - /** - * @return the estimatedSize, in bytes - */ - public long getSizeInBytes() { - return getSize() * BandwidthUtil.BYTES_PER_KILOBYTE; - } - /** * @return the status */ diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java index 456981262d..1935a914aa 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java @@ -44,6 +44,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Jun 25, 2013 2106 djohnson Separate state into other classes, promote BandwidthBucket to a class proper. * Oct 30, 2013 2448 dhladky Moved methods to TimeUtil. * Nov 16, 2013 1736 dhladky Alter size of available bandwidth by subtracting that used by registry. + * Dec 05, 2013 2545 mpduff BandwidthReservation now stored in bytes. * * * @@ -106,7 +107,7 @@ public class RetrievalPlan { void init() { boolean found = false; BandwidthRoute route = map.getRoute(network); - + if (route != null) { found = true; this.planDays = route.getPlanDays(); @@ -115,7 +116,8 @@ public class RetrievalPlan { if (found) { // create registry bandwidth service - RegistryBandwidthService rbs = new RegistryBandwidthService(bucketsDao, network, bucketMinutes); + RegistryBandwidthService rbs = new RegistryBandwidthService( + bucketsDao, network, bucketMinutes); long bucketMillis = bucketMinutes * TimeUtil.MILLIS_PER_MINUTE; Calendar currentBucket = BandwidthUtil.now(); planStart = BandwidthUtil.now(); @@ -126,7 +128,7 @@ public class RetrievalPlan { // Make the buckets... while (!(currentMillis > planEndMillis)) { - + int bw = map.getBandwidth(network, currentBucket); // Get the bucket size.. // buckets are (bandwidth [kilobytes/second] * milliseconds per @@ -136,19 +138,21 @@ public class RetrievalPlan { .convertKilobytesPerSecondToBytesPerSpecifiedMinutes( bw, bucketMinutes); - bucketsDao.create(new BandwidthBucket(currentMillis, bytesPerBucket, - network)); - + bucketsDao.create(new BandwidthBucket(currentMillis, + bytesPerBucket, network)); + currentMillis += bucketMillis; } - + // subtract registry traffic from total available bytes/per second - for (BandwidthBucket bucket: bucketsDao.getAll(network)) { + for (BandwidthBucket bucket : bucketsDao.getAll(network)) { long startMillis = bucket.getBucketStartTime(); - int registryBytesPerSecond = rbs.getRegistryBandwidth(startMillis); - bucket.setBucketSize(bucket.getBucketSize() - (registryBytesPerSecond * TimeUtil.SECONDS_PER_MINUTE * bucketMinutes)); + int registryBytesPerSecond = rbs + .getRegistryBandwidth(startMillis); + bucket.setBucketSize(bucket.getBucketSize() + - (registryBytesPerSecond * TimeUtil.SECONDS_PER_MINUTE * bucketMinutes)); } - + } else { // Can't proceed, throw an Exception throw new IllegalArgumentException( @@ -241,13 +245,16 @@ public class RetrievalPlan { // buckets until we have the new plan size. currentBucketMillis += bucketMillis; // create Registry Bandwidth Service - RegistryBandwidthService rbs = new RegistryBandwidthService(bucketsDao, network, bucketMinutes); - + RegistryBandwidthService rbs = new RegistryBandwidthService( + bucketsDao, network, bucketMinutes); + while (!(currentBucketMillis > newPlanEndMillis)) { - + int bw = map.getBandwidth(network, currentBucket); - // subtract registry traffic from total available bytes/per second - int registryBytesPerSecond = rbs.getRegistryBandwidth(currentBucketMillis); + // subtract registry traffic from total available bytes/per + // second + int registryBytesPerSecond = rbs + .getRegistryBandwidth(currentBucketMillis); bw = bw - registryBytesPerSecond; // Get the bucket size.. // buckets are (bandwidth * kilobytes/second * 60 seconds * @@ -257,7 +264,7 @@ public class RetrievalPlan { bw, bucketMinutes); bucketsDao.create(new BandwidthBucket(currentBucketMillis, bytesPerBucket, network)); - + currentBucketMillis += bucketMillis; statusHandler.info("resize() - Adding bucket [" + bucket + "] bandwidth = [" + bw + "]"); @@ -428,7 +435,7 @@ public class RetrievalPlan { for (Long bucketId : bucketIds) { BandwidthBucket bucket = getBucket(bucketId); bucket.setCurrentSize(bucket.getCurrentSize() - - reservation.getSizeInBytes()); + - reservation.getSize()); associator.removeFromBucket(bucket, reservation); } } @@ -555,7 +562,7 @@ public class RetrievalPlan { synchronized (bucketsLock) { BandwidthBucket actualBucket = getBucket(bucketStartTime); actualBucket.setCurrentSize(actualBucket.getCurrentSize() - + reservation.getSizeInBytes()); + + reservation.getSize()); associator.addToBucket(actualBucket, reservation); } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java index 13b903d0af..3d8882a343 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java @@ -75,6 +75,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Nov 12, 2013 2448 dhladky Fixed stop/start subscription scheduling problem. * Nov 20, 2013 2448 bgonzale Fix for subscription start time set to first cycle time. * Fix for subscription end time set to end of day. + * Dec 02, 2013 2545 mpduff Fix for delay starting retrievals, execute adhoc upon subscribing. * * * @@ -87,7 +88,7 @@ public class BandwidthDaoUtil { private static final IUFStatusHandler statusHandler = UFStatus .getHandler(BandwidthDaoUtil.class); - private final IBandwidthDao bandwidthDao; + private final IBandwidthDao bandwidthDao; private final RetrievalManager retrievalManager; @@ -99,7 +100,7 @@ public class BandwidthDaoUtil { * @param retrievalManager * the retrieval manager */ - public BandwidthDaoUtil(IBandwidthDao bandwidthDao, + public BandwidthDaoUtil(IBandwidthDao bandwidthDao, RetrievalManager retrievalManager) { this.bandwidthDao = bandwidthDao; this.retrievalManager = retrievalManager; @@ -113,8 +114,8 @@ public class BandwidthDaoUtil { * @param cycles * @return */ - public SortedSet getRetrievalTimes(Subscription subscription, - SortedSet cycles) { + public SortedSet getRetrievalTimes( + Subscription subscription, SortedSet cycles) { return getRetrievalTimes(subscription, cycles, Sets.newTreeSet(Arrays.asList(0))); } @@ -128,8 +129,8 @@ public class BandwidthDaoUtil { * the retrieval interval * @return the retrieval times */ - public SortedSet getRetrievalTimes(Subscription subscription, - int retrievalInterval) { + public SortedSet getRetrievalTimes( + Subscription subscription, int retrievalInterval) { // Add all hours of the days final SortedSet hours = Sets.newTreeSet(); for (int i = 0; i < TimeUtil.HOURS_PER_DAY; i++) { @@ -155,8 +156,9 @@ public class BandwidthDaoUtil { * @param minutes * @return */ - private SortedSet getRetrievalTimes(Subscription subscription, - SortedSet hours, SortedSet minutes) { + private SortedSet getRetrievalTimes( + Subscription subscription, SortedSet hours, + SortedSet minutes) { SortedSet subscriptionTimes = new TreeSet(); @@ -174,12 +176,13 @@ public class BandwidthDaoUtil { // the Subscription's active period. if (subscription.getActivePeriodEnd() != null && subscription.getActivePeriodStart() != null) { - + activePeriodStart = TimeUtil.newCalendar(subscription .getActivePeriodStart()); // Substitute the active periods month and day for the // plan start month and day. - Calendar start = BandwidthUtil.planToPeriodCompareCalendar(planStart, activePeriodStart); + Calendar start = BandwidthUtil.planToPeriodCompareCalendar( + planStart, activePeriodStart); // If the active period start is outside the plan bounds, // there is no intersection - just return an empty set. if (start.after(planEnd)) { @@ -187,10 +190,12 @@ public class BandwidthDaoUtil { } // Do the same for active plan end.. - activePeriodEnd = TimeUtil.newCalendar(subscription.getActivePeriodEnd()); + activePeriodEnd = TimeUtil.newCalendar(subscription + .getActivePeriodEnd()); // Substitute the active periods month and day for the // plan ends month and day. - Calendar end = BandwidthUtil.planToPeriodCompareCalendar(planStart, activePeriodEnd); + Calendar end = BandwidthUtil.planToPeriodCompareCalendar(planStart, + activePeriodEnd); // If the active period end is before the start of the plan, // there is no intersection - just return an empty set. if (end.before(planStart)) { @@ -222,7 +227,8 @@ public class BandwidthDaoUtil { // setup active period checks if necessary if (activePeriodStart != null && activePeriodEnd != null) { // need to add the current year in order to make the checks relevant - activePeriodStart = TimeUtil.addCurrentYearCalendar(activePeriodStart); + activePeriodStart = TimeUtil + .addCurrentYearCalendar(activePeriodStart); activePeriodEnd = TimeUtil.addCurrentYearCalendar(activePeriodEnd); // Create a Set of Calendars for all the baseReferenceTimes that a @@ -356,9 +362,9 @@ public class BandwidthDaoUtil { * found */ @SuppressWarnings("rawtypes") - public AdhocSubscription setAdhocMostRecentUrlAndTime( - AdhocSubscription adhoc, boolean mostRecent) { - AdhocSubscription retVal = null; + public AdhocSubscription setAdhocMostRecentUrlAndTime( + AdhocSubscription adhoc, boolean mostRecent) { + AdhocSubscription retVal = null; if (adhoc.getDataSetType() == DataType.POINT) { @@ -377,16 +383,17 @@ public class BandwidthDaoUtil { if (dataSetMetaDatas != null && !dataSetMetaDatas.isEmpty()) { // No guarantee on ordering, have to find most recent time @SuppressWarnings("unchecked") - DataSetMetaData selectedDataSet = dataSetMetaDatas.get(0); + DataSetMetaData selectedDataSet = dataSetMetaDatas + .get(0); Date checkDate = selectedDataSet.getDate(); - - for (DataSetMetaData dsmd: dataSetMetaDatas) { + + for (DataSetMetaData dsmd : dataSetMetaDatas) { if (dsmd.getDate().after(checkDate)) { checkDate = dsmd.getDate(); selectedDataSet = dsmd; } } - + adhoc.setUrl(selectedDataSet.getUrl()); retVal = adhoc; } @@ -411,9 +418,11 @@ public class BandwidthDaoUtil { Time adhocTime = adhoc.getTime(); for (BandwidthDataSetUpdate current : dataSetMetaDataUpdates) { if (mostRecent - || ((GriddedTime)adhocTime).getCycleTimes().contains( - current.getDataSetBaseTime().get( - Calendar.HOUR_OF_DAY))) { + || ((GriddedTime) adhocTime) + .getCycleTimes() + .contains( + current.getDataSetBaseTime() + .get(Calendar.HOUR_OF_DAY))) { daoToUse = current; break; } @@ -442,6 +451,8 @@ public class BandwidthDaoUtil { retVal = adhoc; } } + } else { + retVal = adhoc; } } else { throw new IllegalArgumentException("DataType: " diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthServiceIntTest.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthServiceIntTest.java index 57ca7c7e95..1792689883 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthServiceIntTest.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthServiceIntTest.java @@ -32,7 +32,6 @@ import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.SortedSet; @@ -88,7 +87,8 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Jul 11, 2013 2106 djohnson Use SubscriptionPriority enum. * Jul 18, 2013 1653 mpduff Added test for sub status summary. * Sept 25, 2013 1797 dhladky separated time from gridded time - * Oct 21, 2013 2292 mpduff Implement multiple data types + * Oct 21, 2013 2292 mpduff Implement multiple data types. + * Dec 02, 2013 2545 mpduff Get data by network. * * * @author djohnson @@ -526,7 +526,7 @@ public class BandwidthServiceIntTest BandwidthGraphData graphData = service.getBandwidthGraphData(); assertEquals("Incorrect number of subscriptions returned!", 2, - graphData.getNumberOfSubscriptions()); + graphData.getNumberOfSubscriptions(Network.OPSNET)); } @Test @@ -549,7 +549,8 @@ public class BandwidthServiceIntTest RetrievalPlan opsnetPlan = retrievalManager.getPlan(Network.OPSNET); assertEquals("Incorrect number of subscriptions returned!", - opsnetPlan.getBucketMinutes(), graphData.getBinTimeInMinutes()); + opsnetPlan.getBucketMinutes(), + graphData.getBinTimeInMinutes(Network.OPSNET)); SortedSet descs = graphData .getNetworkBucketMap().get(Network.OPSNET); long earliestTime = descs.first().getBucketStartTime(); @@ -575,11 +576,9 @@ public class BandwidthServiceIntTest bandwidthManager.schedule(subscription); BandwidthGraphData graphData = service.getBandwidthGraphData(); - final Map> dataMap = graphData - .getDataMap(); - final List subscriptionOneTimeWindows = dataMap - .get(subscription.getName()); + final List subscriptionOneTimeWindows = graphData + .getTimeWindowArray(Network.OPSNET, subscription.getName()); assertEquals( "Expected there to be two time windows for this subscription over 2 days", @@ -656,13 +655,11 @@ public class BandwidthServiceIntTest service.schedule(subscription2); BandwidthGraphData graphData = service.getBandwidthGraphData(); - final Map> dataMap = graphData - .getDataMap(); - final List subscriptionOneTimeWindows = dataMap - .get(subscription.getName()); - final List subscriptionTwoTimeWindows = dataMap - .get(subscription2.getName()); + final List subscriptionOneTimeWindows = graphData + .getTimeWindowArray(Network.OPSNET, subscription.getName()); + final List subscriptionTwoTimeWindows = graphData + .getTimeWindowArray(Network.OPSNET, subscription2.getName()); assertEquals( "Expected there to be four retrievals for this subscription over 2 days", @@ -691,13 +688,12 @@ public class BandwidthServiceIntTest service.schedule(subscription2); BandwidthGraphData graphData = service.getBandwidthGraphData(); - final Map priorityMap = graphData - .getPriorityMap(); - - assertThat(priorityMap.get(subscription.getName()), + assertThat( + graphData.getPriority(Network.OPSNET, subscription.getName()), is(equalTo(subscription.getPriority()))); - assertThat(priorityMap.get(subscription2.getName()), + assertThat( + graphData.getPriority(Network.OPSNET, subscription2.getName()), is(equalTo(subscription2.getPriority()))); } diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapterTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapterTest.java new file mode 100644 index 0000000000..bf2d95e777 --- /dev/null +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthGraphDataAdapterTest.java @@ -0,0 +1,173 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.datadelivery.bandwidth; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.junit.Before; +import org.junit.Test; + +import com.raytheon.uf.common.datadelivery.bandwidth.data.BandwidthBucketDescription; +import com.raytheon.uf.common.datadelivery.registry.Network; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.edex.datadelivery.bandwidth.dao.BandwidthBucket; +import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalManager; +import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalPlan; + +/** + * Test class for {@link BandwidthGraphdataAdapter}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Nov 25, 2013            mpduff     Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class BandwidthGraphDataAdapterTest { + + private static final int BUCKET_SIZE = 100; + + private static final RetrievalManager retrievalManagerMock = mock(RetrievalManager.class); + + private static final RetrievalPlan retrievalPlan = new RetrievalPlan(); + + private static final SortedSet bucketSet = new TreeSet(); + + private static final BandwidthGraphDataAdapter adapter = new BandwidthGraphDataAdapter( + retrievalManagerMock); + + @Before + public void classSetup() { + bucketSet.clear(); + long bucketSizeMinutes = 3 * TimeUtil.MILLIS_PER_MINUTE; + long bucketStart = bucketSizeMinutes; + + // Create 10 buckets + for (int i = 0; i < 10; i++) { + BandwidthBucket bucket = new BandwidthBucket(bucketStart, + BUCKET_SIZE, Network.OPSNET); + bucketSet.add(bucket); + bucketStart += bucketSizeMinutes; + } + } + + @Test + public void testAdapterCreatesTheCorrectNumberObjects() { + SortedSet descriptions = adapter + .toDescriptions(bucketSet); + + assertTrue("Incorrect number of descriptions created", + descriptions.size() == bucketSet.size()); + } + + @Test + public void testToDescriptionFillsOneBucketOnly() { + Iterator iter = bucketSet.iterator(); + + // Get the first bucket and fill it full + BandwidthBucket bucket = iter.next(); + bucket.setCurrentSize(BUCKET_SIZE); + + int idx = 0; + SortedSet descriptions = adapter + .toDescriptions(bucketSet); + + Iterator it = descriptions.iterator(); + while (it.hasNext()) { + BandwidthBucketDescription bbd = it.next(); + if (idx == 0) { + assertTrue("First bucket should be full", + bbd.getUsedBytes() == bucket.getBucketSize()); + idx++; + } else { + assertTrue("Bucket should be empty", bbd.getUsedBytes() == 0); + } + } + } + + @Test + public void testToDescriptionFillsTwoBucketsFull() { + Iterator iter = bucketSet.iterator(); + + // Get the first 2 buckets and fill them full + BandwidthBucket bucket = iter.next(); + bucket.setCurrentSize(BUCKET_SIZE); + bucket = iter.next(); + bucket.setCurrentSize(BUCKET_SIZE); + + int idx = 0; + SortedSet descriptions = adapter + .toDescriptions(bucketSet); + + Iterator it = descriptions.iterator(); + while (it.hasNext()) { + BandwidthBucketDescription bbd = it.next(); + if (idx == 0 || idx == 1) { + assertTrue("First two buckets should be full", + bbd.getUsedBytes() == bucket.getBucketSize()); + idx++; + } else { + assertTrue("Bucket should be empty", bbd.getUsedBytes() == 0); + } + } + } + + @Test + public void testOverfilledBucketsOverflowToLaterBuckets() { + Iterator iter = bucketSet.iterator(); + + // Get the first bucket and fill it 4.5 buckets worth + BandwidthBucket bucket = iter.next(); + bucket.setCurrentSize((BUCKET_SIZE * 4) + (BUCKET_SIZE / 2)); + + int idx = 0; + SortedSet descriptions = adapter + .toDescriptions(bucketSet); + + Iterator it = descriptions.iterator(); + while (it.hasNext()) { + BandwidthBucketDescription bbd = it.next(); + if (idx <= 3) { + assertTrue("First four buckets should be full", + bbd.getUsedBytes() == bucket.getBucketSize()); + idx++; + } else if (idx == 4) { + assertTrue("Bucket should be half full", + bbd.getUsedBytes() == bucket.getBucketSize() / 2); + idx++; + } else { + assertTrue("Bucket should be empty", bbd.getUsedBytes() == 0); + } + } + } +}