Issue #1596 Do not reschedule bandwidth allocations when a subscription is removed
Change-Id: I4016034e6bdc5e8acf4936a0f786906611e7ad41 Former-commit-id:4be6c12ac6
[formerly714ea1c8d8
] [formerly6e2f69939f
[formerly 5f87319abc3712667abc6b454f49882b0f3fb45f]] Former-commit-id:6e2f69939f
Former-commit-id:1ef440f8ee
This commit is contained in:
parent
0156736b85
commit
d0ecd69456
5 changed files with 179 additions and 72 deletions
|
@ -30,13 +30,12 @@ import com.raytheon.uf.common.status.UFStatus;
|
|||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.requests.ThriftClient;
|
||||
import com.raytheon.uf.viz.datadelivery.actions.BandwidthScheduleGraphAction;
|
||||
|
||||
/**
|
||||
*
|
||||
* This is a utility class used to get data for the bandwidth graph it extends
|
||||
* the Thread class so you can retrieve data on a separate thread to keep the UI
|
||||
* thread from being blocked.
|
||||
* This is a utility class used to get data for the bandwidth graph it
|
||||
* implements {@link Runnable} so you can retrieve data on a separate thread to
|
||||
* keep the UI thread from being blocked.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -45,19 +44,20 @@ import com.raytheon.uf.viz.datadelivery.actions.BandwidthScheduleGraphAction;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 12, 2012 1269 lvenable Initial creation
|
||||
* Feb 14, 2013 1596 djohnson Remove sysouts, correct statusHandler class, handle null response.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author lvenable
|
||||
* @version 1.0
|
||||
*/
|
||||
public class GraphDataUtil extends Thread {
|
||||
public class GraphDataUtil implements Runnable {
|
||||
/** UFStatus handler */
|
||||
private final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(BandwidthScheduleGraphAction.class);
|
||||
.getHandler(GraphDataUtil.class);
|
||||
|
||||
/** Graph data request object */
|
||||
private GraphDataRequest request;
|
||||
private final GraphDataRequest request = new GraphDataRequest();
|
||||
|
||||
/** Graph data response object */
|
||||
private GraphDataResponse response;
|
||||
|
@ -79,7 +79,6 @@ public class GraphDataUtil extends Thread {
|
|||
* thread.
|
||||
*/
|
||||
public GraphDataUtil(IDataUpdated dataUpdatedCB) {
|
||||
request = new GraphDataRequest();
|
||||
this.dataUpdatedCB = dataUpdatedCB;
|
||||
}
|
||||
|
||||
|
@ -99,7 +98,10 @@ public class GraphDataUtil extends Thread {
|
|||
*/
|
||||
public void retrieveData() {
|
||||
response = sendRequest(request);
|
||||
graphData = response.getGraphData();
|
||||
|
||||
if (response != null) {
|
||||
graphData = response.getGraphData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,14 +157,13 @@ public class GraphDataUtil extends Thread {
|
|||
/**
|
||||
* Thread run method to retrieve the graph data.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Thread - retrieving data...");
|
||||
retrieveData();
|
||||
|
||||
if (dataUpdatedCB != null) {
|
||||
dataUpdatedCB.dataUpdated();
|
||||
}
|
||||
|
||||
System.out.println("Thread - DONE retrieving data...");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ import java.util.regex.Pattern;
|
|||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.AllowConcurrentEvents;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
@ -101,6 +99,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil;
|
|||
* Jan 30, 2013 1501 djohnson Fix broken calculations for determining required latency.
|
||||
* Feb 05, 2013 1580 mpduff EventBus refactor.
|
||||
* Feb 14, 2013 1595 djohnson Check with BandwidthUtil whether or not to reschedule subscriptions on update.
|
||||
* Feb 14, 2013 1596 djohnson Do not reschedule allocations when a subscription is removed.
|
||||
* </pre>
|
||||
*
|
||||
* @author dhladky
|
||||
|
@ -560,7 +559,7 @@ abstract class BandwidthManager extends
|
|||
List<BandwidthSubscription> l = bandwidthDao
|
||||
.getBandwidthSubscriptionByRegistryId(event.getId());
|
||||
if (!l.isEmpty()) {
|
||||
remove(l, true);
|
||||
remove(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -736,7 +735,7 @@ abstract class BandwidthManager extends
|
|||
// See if the subscription was inactivated or unscheduled..
|
||||
// Need to remove BandwidthReservations for this
|
||||
// subscription.
|
||||
return remove(bandwidthSubscriptions, true);
|
||||
return remove(bandwidthSubscriptions);
|
||||
} else {
|
||||
|
||||
// Compare the 'updated' Subscription with the stored
|
||||
|
@ -761,8 +760,7 @@ abstract class BandwidthManager extends
|
|||
|
||||
// OK, have to remove the old Subscriptions and add the new
|
||||
// ones..
|
||||
List<BandwidthAllocation> unscheduled = remove(
|
||||
bandwidthSubscriptions, false);
|
||||
List<BandwidthAllocation> unscheduled = remove(bandwidthSubscriptions);
|
||||
// No need to check anything else since all the
|
||||
// BandwidthSubscription's have been replaced.
|
||||
unscheduled.addAll(schedule(subscription));
|
||||
|
@ -794,10 +792,10 @@ abstract class BandwidthManager extends
|
|||
newCycles.removeAll(commonCycles);
|
||||
|
||||
// Remove the old cycles, add the new ones...
|
||||
if (oldCycles.size() > 0) {
|
||||
if (!oldCycles.isEmpty()) {
|
||||
// Create a List of SubscriptionDaos that need to be
|
||||
// removed..
|
||||
List<BandwidthSubscription> remove = new ArrayList<BandwidthSubscription>();
|
||||
List<BandwidthSubscription> bandwidthSubscriptionToRemove = new ArrayList<BandwidthSubscription>();
|
||||
BandwidthSubscription bandwidthSubscription = null;
|
||||
Iterator<BandwidthSubscription> itr = bandwidthSubscriptions
|
||||
.iterator();
|
||||
|
@ -805,11 +803,11 @@ abstract class BandwidthManager extends
|
|||
bandwidthSubscription = itr.next();
|
||||
if (oldCycles.contains(bandwidthSubscription
|
||||
.getCycle())) {
|
||||
remove.add(bandwidthSubscription);
|
||||
bandwidthSubscriptionToRemove.add(bandwidthSubscription);
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
unscheduled.addAll(remove(remove, true));
|
||||
unscheduled.addAll(remove(bandwidthSubscriptionToRemove));
|
||||
}
|
||||
|
||||
if (newCycles.size() > 0) {
|
||||
|
@ -846,63 +844,15 @@ abstract class BandwidthManager extends
|
|||
*
|
||||
* @param bandwidthSubscriptions
|
||||
* The subscriptionDao's to remove.
|
||||
* @param reschedule
|
||||
* @return
|
||||
*/
|
||||
private List<BandwidthAllocation> remove(
|
||||
List<BandwidthSubscription> bandwidthSubscriptions,
|
||||
boolean reschedule) {
|
||||
List<BandwidthSubscription> bandwidthSubscriptions) {
|
||||
|
||||
List<BandwidthAllocation> unscheduled = new ArrayList<BandwidthAllocation>();
|
||||
|
||||
// If we need to reschedule other bandwidth reservations when we
|
||||
// remove the provided BandwidthSubscription's then we have to retrieve
|
||||
// all the SubscriptionRetrieval records that are scheduled for
|
||||
// the same base time.
|
||||
if (reschedule) {
|
||||
|
||||
// First create a map of base times to subscriptions
|
||||
Multimap<Calendar, BandwidthSubscription> map = ArrayListMultimap
|
||||
.create();
|
||||
|
||||
for (BandwidthSubscription bandwidthSubscription : bandwidthSubscriptions) {
|
||||
|
||||
Calendar time = bandwidthSubscription.getBaseReferenceTime();
|
||||
map.put(time, bandwidthSubscription);
|
||||
}
|
||||
|
||||
// Now process each time group by dataset..
|
||||
for (Calendar baseTime : map.keySet()) {
|
||||
|
||||
// For each date, get a unique set of provider & dataset name
|
||||
Set<String> providerDataSet = new HashSet<String>();
|
||||
for (BandwidthSubscription bandwidthSubscription : map
|
||||
.get(baseTime)) {
|
||||
String key = bandwidthSubscription.getProvider() + "::"
|
||||
+ bandwidthSubscription.getDataSetName();
|
||||
providerDataSet.add(key);
|
||||
bandwidthDaoUtil.remove(bandwidthSubscription);
|
||||
}
|
||||
|
||||
// Query for and reschedule any SubscriptionRetrieval
|
||||
// Objects associated with the Queried BandwidthSubscription's
|
||||
for (String providerDataSetName : providerDataSet) {
|
||||
String[] key = providerDataSetName.split("::");
|
||||
String provider = key[0];
|
||||
String dataSetName = key[1];
|
||||
List<BandwidthSubscription> m = bandwidthDao
|
||||
.getBandwidthSubscriptions(provider, dataSetName,
|
||||
baseTime);
|
||||
|
||||
unscheduled.addAll(aggregate(m));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (BandwidthSubscription bandwidthSubscription : bandwidthSubscriptions) {
|
||||
bandwidthDaoUtil.remove(bandwidthSubscription);
|
||||
}
|
||||
for (BandwidthSubscription bandwidthSubscription : bandwidthSubscriptions) {
|
||||
bandwidthDaoUtil.remove(bandwidthSubscription);
|
||||
}
|
||||
|
||||
return unscheduled;
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.RetrievalManagerNotifyEvent;
|
|||
* change the event listener type.
|
||||
* Oct 26, 2012 1286 djohnson Return list of unscheduled allocations.
|
||||
* Feb 05, 2013 1580 mpduff EventBus refactor.
|
||||
* Feb 14, 2013 1596 djohnson Warn log when unable to find a SubscriptionRetrieval.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -136,6 +137,12 @@ public class RetrievalManager {
|
|||
SubscriptionRetrieval subscriptionRetrieval = bandwidthDao
|
||||
.getSubscriptionRetrieval(eventId);
|
||||
|
||||
if (subscriptionRetrieval == null) {
|
||||
statusHandler.warn("Unable to find SubscriptionRetrieval by id ["
|
||||
+ eventId + "]");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the SubscriptionRetrieval in the database since the Retrievals
|
||||
// were completed outside the Bandwidth subsystem.
|
||||
subscriptionRetrieval.setStatus(RetrievalStatus.FULFILLED);
|
||||
|
|
|
@ -21,6 +21,7 @@ package com.raytheon.uf.edex.datadelivery.bandwidth;
|
|||
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -98,6 +99,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.RetrievalManagerNotifyEvent;
|
|||
* Jan 28, 2013 1530 djohnson Test that all allocations are unscheduled for subscription that doesn't fully schedule.
|
||||
* Jan 30, 2013 1501 djohnson Fix broken calculations for determining required latency.
|
||||
* Feb 14, 2013 1595 djohnson Fix expired subscription updates that weren't scheduling retrievals.
|
||||
* Feb 14, 2013 1596 djohnson Add test duplicating errors deleting multiple subscriptions for the same provider/dataset.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -776,6 +778,85 @@ public class BandwidthManagerIntTest extends AbstractBandwidthManagerIntTest {
|
|||
subscriptionDaosAfterDelete.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case derived from Redmine #1596: There were 5 or 6 subscriptions
|
||||
* that were deleted simultaneously. All subscriptions were removed from the
|
||||
* Subscription Manager dialog...however, 2 subscriptions remained
|
||||
* 'scheduled' or listed on the Bandwidth Utilization graph. After selecting
|
||||
* the deleted subscription in the Bandwidth Utilization graph, the view
|
||||
* selected subscriptions option was selected. No subscriptions were
|
||||
* displayed, as expected...even though the subscription was listed in the
|
||||
* Bandwidth Utilization graph.
|
||||
*/
|
||||
@Test
|
||||
public void testDeletedSubscriptionsToSameProviderDataSetHaveSubscriptionDaosDeletedFromDatabase()
|
||||
throws Exception {
|
||||
|
||||
final int numberOfSubscriptionsWithSameProviderDataSet = 4;
|
||||
|
||||
final Subscription templateSubscription = createSubscriptionThatFillsUpABucket();
|
||||
final Network route = templateSubscription.getRoute();
|
||||
templateSubscription.setDataSetSize(templateSubscription
|
||||
.getDataSetSize()
|
||||
/ numberOfSubscriptionsWithSameProviderDataSet);
|
||||
|
||||
templateSubscription.getTime().setCycleTimes(Arrays.asList(0, 12));
|
||||
|
||||
int lastKnownNumberOfBandwidthAllocations = 0;
|
||||
final Subscription[] subscriptions = new Subscription[numberOfSubscriptionsWithSameProviderDataSet];
|
||||
for (int i = 0; i < numberOfSubscriptionsWithSameProviderDataSet; i++) {
|
||||
|
||||
final Subscription currentSubscription = new Subscription(
|
||||
templateSubscription, "ILookLikeTheOtherGuys-" + i);
|
||||
subscriptions[i] = currentSubscription;
|
||||
|
||||
bandwidthManager.schedule(currentSubscription);
|
||||
|
||||
// Make sure some data is scheduled for retrieval
|
||||
final int currentNumberOfBandwidthAllocations = bandwidthDao
|
||||
.getBandwidthAllocations(route).size();
|
||||
assertThat(currentNumberOfBandwidthAllocations,
|
||||
is(greaterThan(lastKnownNumberOfBandwidthAllocations)));
|
||||
|
||||
// Update last known number of bandwidth allocations, so we can
|
||||
// continue verifying more is scheduled
|
||||
lastKnownNumberOfBandwidthAllocations = currentNumberOfBandwidthAllocations;
|
||||
}
|
||||
|
||||
// Schedule two subscription deletions to occur at the same time
|
||||
final CountDownLatch waitForAllThreadsToStartLatch = new CountDownLatch(
|
||||
numberOfSubscriptionsWithSameProviderDataSet);
|
||||
final CountDownLatch deletesFinishedLatch = new CountDownLatch(
|
||||
numberOfSubscriptionsWithSameProviderDataSet);
|
||||
|
||||
for (int i = 0; i < numberOfSubscriptionsWithSameProviderDataSet; i++) {
|
||||
final int iteration = i;
|
||||
final Thread deleteSubscriptionThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
waitForAllThreadsToStartLatch.countDown();
|
||||
try {
|
||||
sendDeletedSubscriptionEvent(subscriptions[iteration]);
|
||||
} finally {
|
||||
deletesFinishedLatch.countDown();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Delete the subscription! Each thread will wait to perform the
|
||||
// deletion until all threads are started.
|
||||
deleteSubscriptionThread.start();
|
||||
}
|
||||
|
||||
// Wait for the deletion threads to finish
|
||||
deletesFinishedLatch.await();
|
||||
|
||||
// Better not be any bandwidth subscriptions left, or bandwidth
|
||||
// allocations
|
||||
assertThat(bandwidthDao.getBandwidthSubscriptions(), is(empty()));
|
||||
assertThat(bandwidthDao.getBandwidthAllocations(route), is(empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscriptions that are deleted should have all of their bandwidth
|
||||
* allocations removed deleted.
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* 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.retrieval;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.raytheon.uf.edex.datadelivery.bandwidth.dao.IBandwidthDao;
|
||||
import com.raytheon.uf.edex.datadelivery.retrieval.RetrievalManagerNotifyEvent;
|
||||
|
||||
/**
|
||||
* Test {@link RetrievalManager}.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 14, 2013 1543 djohnson Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author djohnson
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class RetrievalManagerTest {
|
||||
|
||||
private static final long EVENT_ID = 1L;
|
||||
|
||||
private final IBandwidthDao dao = mock(IBandwidthDao.class);
|
||||
|
||||
private final RetrievalManagerNotifyEvent event = new RetrievalManagerNotifyEvent();
|
||||
{
|
||||
event.setId(Long.valueOf(EVENT_ID).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSubscriptionRetrievalByEventIdDoesNotThrowException() {
|
||||
when(dao.getSubscriptionRetrieval(EVENT_ID)).thenReturn(null);
|
||||
|
||||
RetrievalManager retrievalManager = new RetrievalManager(dao,
|
||||
new Object());
|
||||
|
||||
retrievalManager.retrievalCompleted(event);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue