Issue #2220 Better response using priority queues and delay getting display data.

Change-Id: I5f7b8eb904dcde9ef52acc2f39df864ac62080bb

Former-commit-id: f6f5a236056e2d3cbbcd2fdb3a1efa1c76ef5178
This commit is contained in:
Roger Ferrel 2013-08-08 08:03:26 -05:00 committed by Richard Peter
parent 3569155bc0
commit 76a6afc46f
8 changed files with 666 additions and 278 deletions

View file

@ -36,6 +36,7 @@ import com.raytheon.uf.common.archive.config.DisplayData;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 24, 2013 1966 rferrel Initial creation
* Aug 14, 2013 2220 rferrel Make sure displayDataList is never null.
*
* </pre>
*
@ -61,22 +62,46 @@ public class CategoryInfo {
* @param displayInfoList
*/
public CategoryInfo(String archiveName, String categoryName,
List<DisplayData> displayInfoList) {
List<DisplayData> displayDataList) {
this.archiveName = archiveName;
this.categoryName = categoryName;
this.displayDataList = new ArrayList<DisplayData>(
displayInfoList.size());
this.displayDataList.addAll(displayInfoList);
if (displayDataList == null) {
this.displayDataList = new ArrayList<DisplayData>(0);
} else {
setDisplayDataList(displayDataList);
}
}
/**
* Change the display data list.
*
* @param displayDataList
*/
public void setDisplayDataList(List<DisplayData> displayDataList) {
this.displayDataList = new ArrayList<DisplayData>(
displayDataList.size());
this.displayDataList.addAll(displayDataList);
}
/**
* @return archiveName
*/
public String getArchiveName() {
return archiveName;
}
/**
* @return categoryName
*/
public String getCategoryName() {
return categoryName;
}
/**
* Get unmodifiable display data list.
*
* @return displayDataList
*/
public List<DisplayData> getDisplayDataList() {
return Collections.unmodifiableList(displayDataList);
}

View file

@ -0,0 +1,47 @@
/**
* 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.viz.archive.data;
/**
* Interface to adjusting values based on the retention hour value found in a
* selection configuration.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 13, 2013 2220 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public interface IRetentionHour {
/**
* Adjust start/end based on the value found in selection configuration.
*
* @param startRetentionHours
*/
public void setRetentionTimes(long startRetentionHours);
}

View file

@ -3,12 +3,18 @@ package com.raytheon.uf.viz.archive.data;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.runtime.IProgressMonitor;
@ -52,6 +58,11 @@ public class SizeJob extends Job {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(SizeJob.class);
/**
* The private variable from PriorityQueue.
*/
private final int DEFAULT_INITIAL_CAPACITY = 11;
/**
* Mapping of display data by archive and category names.
*/
@ -74,28 +85,23 @@ public class SizeJob extends Job {
private final AtomicBoolean displaySizesComputed = new AtomicBoolean(false);
/**
* Request queue for selected data not in current display
* Queue of display data needing sizes.
*/
private final ConcurrentLinkedQueue<DisplayData> selectedQueue = new ConcurrentLinkedQueue<DisplayData>();
private final PriorityBlockingQueue<DisplayData> sizeQueue = new PriorityBlockingQueue<DisplayData>(
DEFAULT_INITIAL_CAPACITY, DisplayData.PRIORITY_ORDER);
/**
* Request queue for data not in current displayed or selected.
* Data to send to listeners.
*/
private final ConcurrentLinkedQueue<DisplayData> backgroundQueue = new ConcurrentLinkedQueue<DisplayData>();
private final LinkedBlockingQueue<DisplayData> displayQueue = new LinkedBlockingQueue<DisplayData>();
/**
* Indicates the job should stop computing the size of the current
* non-selected entry.
* Current list of visible data.
*/
private final AtomicBoolean stopComputeSize = new AtomicBoolean(false);
private List<DisplayData> visibleList = new ArrayList<DisplayData>(0);
/**
* What should happen to the processing request that is being stopped.
*/
private final AtomicBoolean requeueRequest = new AtomicBoolean(false);
/**
* Set to true when running job should stop and never rescheduled.
* Set to true when running job should stop and never be rescheduled.
*/
private final AtomicBoolean shutdown = new AtomicBoolean(false);
@ -104,15 +110,83 @@ public class SizeJob extends Job {
*/
private final List<IUpdateListener> listeners = new ArrayList<IUpdateListener>();
/**
* The display data whose size is being computed.
*/
private DisplayData currentDisplayData;
/**
* Method to call when loading a new selection for retention/case creation
* to update times.
*/
private IRetentionHour iRetentionHour;
/**
* Current start time.
*/
Calendar startCal;
private Calendar startCal;
/**
* Current end time.
*/
Calendar endCal;
private Calendar endCal;
/**
* Timer to periodically update the GUI display computed sizes.
*/
private Timer displayTimer;
/**
* Flag to shutdown the display timer.
*/
private final AtomicBoolean shutdownDisplayTimer = new AtomicBoolean(false);
/**
* Frequency for performing peek while computing sizes.
*/
private final int peekFrequency = 50;
/**
* Counter to reduce the number of times a peek is performed while computing
* sizes.
*/
private int peekCnt;
/**
* Flag to stop computing sizes; only accessed by a single thread.
*/
private boolean stopComputeSize;
/**
* Priority queue for getting display data for an archive/category.
*/
// Do not use a PriorityBlockingQueue since the load select and change
// display methods need to be notified when the display data is available.
private final PriorityQueue<MissingData> missingDataQueue = new PriorityQueue<SizeJob.MissingData>(
DEFAULT_INITIAL_CAPACITY, new Comparator<MissingData>() {
@Override
public int compare(MissingData o1, MissingData o2) {
if (o1.visiable != o2.visiable) {
return o1.visiable ? -1 : +1;
}
if (o1.isSelected() != o2.isSelected()) {
return o1.isSelected() ? -1 : +1;
}
int result = o1.archive.compareToIgnoreCase(o2.archive);
if (result == 0) {
result = o1.category.compareToIgnoreCase(o2.category);
}
return result;
}
});
/**
* Job for processing the missing data queue.
*/
private final MissingDataJob missingDataJob = new MissingDataJob();
/**
* Constructor.
@ -163,11 +237,8 @@ public class SizeJob extends Job {
for (DisplayData displayData : categoryInfo
.getDisplayDataList()) {
displayData.setSize(DisplayData.UNKNOWN_SIZE);
if (displayData.isSelected()) {
selectedQueue.add(displayData);
} else {
backgroundQueue.add(displayData);
}
sizeQueue.add(displayData);
if (shutdown.get()) {
return;
}
@ -183,28 +254,6 @@ public class SizeJob extends Job {
}
}
/**
* If request is for unknown size then add request to the appropriate queue.
*
* @param fileInfo
*/
private void requeue(DisplayData displayData) {
if (!shutdown.get()) {
requeueRequest.set(false);
if (displayData.isSelected()) {
selectedQueue.add(displayData);
backgroundQueue.remove(displayData);
} else {
selectedQueue.remove(displayData);
backgroundQueue.add(displayData);
}
if (getState() == Job.NONE) {
schedule();
}
}
}
/**
* Add entry to the archive information map.
*
@ -212,10 +261,6 @@ public class SizeJob extends Job {
* @param archiveInfo
*/
public void put(String archiveName, ArchiveInfo archiveInfo) {
if (archiveInfoMap.isEmpty()) {
displayArchive = archiveName;
displayCategory = archiveInfo.getCategoryNames().iterator().next();
}
archiveInfoMap.put(archiveName, archiveInfo);
}
@ -237,8 +282,8 @@ public class SizeJob extends Job {
}
/**
* Set the display data's select state and check to see if it needs to be
* requeue.
* Check all displayData selection state so only the data in selections are
* set.
*
* @param selections
*/
@ -250,19 +295,28 @@ public class SizeJob extends Job {
selections = new SelectConfig();
selections.setName(ArchiveConstants.defaultSelectName);
}
iRetentionHour.setRetentionTimes(selections.getStarRetentionHours());
for (String archiveName : getArchiveNames()) {
ArchiveInfo archiveInfo = get(archiveName);
for (String categoryName : archiveInfo.getCategoryNames()) {
CategoryInfo categoryInfo = archiveInfo.get(categoryName);
List<String> selectionsList = selections.getSelectedList(
archiveName, categoryName);
for (DisplayData displayData : categoryInfo
.getDisplayDataList()) {
String displayLabel = displayData.getDisplayLabel();
boolean selected = selectionsList.contains(displayLabel);
if (selected != displayData.isSelected()) {
setSelect(displayData, selected);
MissingData missingData = removeMissingData(archiveName,
categoryName);
if (missingData != null) {
missingData.setSelectedList(selectionsList);
addMissingData(missingData);
} else {
CategoryInfo categoryInfo = archiveInfo.get(categoryName);
for (DisplayData displayData : categoryInfo
.getDisplayDataList()) {
String displayLabel = displayData.getDisplayLabel();
boolean selected = selectionsList
.contains(displayLabel);
if (selected != displayData.isSelected()) {
setSelect(displayData, selected);
}
}
}
}
@ -275,6 +329,16 @@ public class SizeJob extends Job {
* @return selected
*/
public List<DisplayData> getSelectAll() {
synchronized (missingDataQueue) {
while (!missingDataQueue.isEmpty()) {
if (missingDataJob.currentMissingData == null
|| missingDataJob.currentMissingData.isSelected()) {
missingDataQueueWait();
} else {
break;
}
}
}
List<DisplayData> selected = new LinkedList<DisplayData>();
for (ArchiveInfo archiveInfo : archiveInfoMap.values()) {
for (String categoryName : archiveInfo.getCategoryNames()) {
@ -344,16 +408,35 @@ public class SizeJob extends Job {
}
/**
* Update the selection state and if needed requeue size request.
* Change the selection state and reset priority.
*
* @param displayData
* @param state
*/
public void setSelect(DisplayData displayData, boolean state) {
if (displayData.isSelected() != state) {
displayData.setSelected(state);
if (displayData.getSize() == DisplayData.UNKNOWN_SIZE) {
requeue(displayData);
if (sizeQueue.remove(displayData)) {
displayData.setSelected(state);
sizeQueue.add(displayData);
} else {
displayData.setSelected(state);
}
}
}
/**
* Change visibility state and reset priority.
*
* @param displayData
* @param state
*/
private void setVisible(DisplayData displayData, boolean state) {
if (displayData.isVisible() != state) {
if (sizeQueue.remove(displayData)) {
displayData.setVisible(state);
sizeQueue.add(displayData);
} else {
displayData.setVisible(state);
}
}
}
@ -363,32 +446,184 @@ public class SizeJob extends Job {
*
* @param archiveName
* @param categoryName
* @return displayData when display needs to change otherwise null
*/
public void changeDisplayQueue(String archiveName, String categoryName) {
if (archiveName == null) {
if (displayArchive != null) {
synchronized (this) {
if (!displaySizesComputed.get() && !selectedQueue.isEmpty()) {
requeueRequest.set(true);
stopComputeSize.set(true);
displayArchive = null;
displaySizesComputed.set(true);
public List<DisplayData> changeDisplay(String archiveName,
String categoryName) {
List<DisplayData> displayDatas = null;
if (!archiveName.equals(displayArchive)
|| !categoryName.equals(displayCategory)) {
MissingData missingData = removeMissingData(archiveName,
categoryName);
if (missingData != null) {
missingData.setVisiable(true);
synchronized (missingDataQueue) {
addMissingData(missingData);
while (missingDataQueue.contains(missingData)) {
missingDataQueueWait();
}
}
}
return;
displayDatas = archiveInfoMap.get(archiveName).get(categoryName)
.getDisplayDataList();
displayArchive = archiveName;
displayCategory = categoryName;
changeDisplay(displayDatas);
}
if (!archiveName.equals(displayArchive)
|| !categoryName.equals(displayCategory)) {
synchronized (this) {
if (getState() != Job.NONE) {
requeueRequest.set(true);
stopComputeSize.set(true);
return displayDatas;
}
/**
* Change to display all selected data..
*
* @return displayhData when display needs to change otherwise null.
*/
public List<DisplayData> changeDisplayAll() {
List<DisplayData> selectedData = null;
if (displayArchive != null) {
displayArchive = null;
displayCategory = null;
selectedData = getSelectAll();
changeDisplay(selectedData);
}
return selectedData;
}
public String initData(ArchiveConstants.Type type, String selectName,
String displayArchive, String displayCategory,
IRetentionHour iRetentionHour) {
this.iRetentionHour = iRetentionHour;
ArchiveConfigManager manager = ArchiveConfigManager.getInstance();
String fileName = ArchiveConstants.selectFileName(type, selectName);
SelectConfig selections = manager.loadSelection(fileName);
if (selections == null) {
selections = new SelectConfig();
selections.setName(ArchiveConstants.defaultSelectName);
}
iRetentionHour.setRetentionTimes(selections.getStarRetentionHours());
missingDataQueue.clear();
visibleList = manager.getDisplayData(displayArchive, displayCategory,
false);
List<String> selectedList = selections.getSelectedList(displayArchive,
displayCategory);
for (DisplayData displayData : visibleList) {
displayData.setSelected(selectedList.contains(displayData
.getDisplayLabel()));
}
for (String archiveName : manager.getArchiveDataNamesList()) {
ArchiveInfo archiveInfo = new ArchiveInfo();
String[] categoryNames = manager.getCategoryNames(manager
.getArchive(archiveName));
for (String categoryName : categoryNames) {
CategoryInfo categoryInfo = new CategoryInfo(archiveName,
categoryName, null);
archiveInfo.add(categoryInfo);
if (archiveName.equals(displayArchive)
&& categoryName.equals(displayCategory)) {
categoryInfo.setDisplayDataList(visibleList);
if (!visibleList.isEmpty()) {
schedule();
}
} else {
selectedList = selections.getSelectedList(archiveName,
categoryName);
MissingData missingData = new MissingData(archiveName,
categoryName, selectedList);
missingDataQueue.add(missingData);
}
displaySizesComputed.set(false);
displayArchive = archiveName;
displayCategory = categoryName;
}
put(archiveName, archiveInfo);
}
missingDataJob.schedule();
return selections.getName();
}
/**
* Find and remove the missing data from the missing data queue.
*
* @param archiveName
* @param categoryName
* @return missingData or null if not on the missing data queue
*/
private MissingData removeMissingData(String archiveName,
String categoryName) {
MissingData missingData = null;
synchronized (missingDataQueue) {
if (missingDataJob.currentMissingData != null
&& archiveName
.equals(missingDataJob.currentMissingData.archive)
&& categoryName
.equals(missingDataJob.currentMissingData.category)) {
// Finish the process of getting the data.
missingDataQueueWait();
} else if (!missingDataQueue.isEmpty()) {
Iterator<MissingData> iterator = missingDataQueue.iterator();
while (iterator.hasNext()) {
MissingData md = iterator.next();
if (md.archive.equals(archiveName)
&& md.category.equals(categoryName)) {
iterator.remove();
missingData = md;
break;
}
}
}
}
return missingData;
}
/**
* Wait for notification that current missing data is finished processing.
*
* @return false when interrupted exception
*/
private boolean missingDataQueueWait() {
boolean state = true;
try {
missingDataQueue.wait();
} catch (InterruptedException e) {
state = false;
statusHandler.handle(Priority.INFO, e.getLocalizedMessage(), e);
}
return state;
}
/**
*
* @param missingData
*/
private void addMissingData(MissingData missingData) {
synchronized (missingDataQueue) {
missingDataQueue.add(missingData);
if (missingDataJob.getState() == Job.NONE) {
missingDataJob.schedule();
}
}
}
/**
* Change update visible to the new list.
*
* @param newDisplays
*/
private void changeDisplay(List<DisplayData> newDisplays) {
List<DisplayData> oldDisplays = visibleList;
visibleList = newDisplays;
List<DisplayData> visibleList = new ArrayList<DisplayData>(newDisplays);
for (DisplayData displayData : oldDisplays) {
if (!visibleList.remove(displayData)) {
setVisible(displayData, false);
}
}
for (DisplayData displayData : visibleList) {
setVisible(displayData, true);
}
}
@ -396,13 +631,8 @@ public class SizeJob extends Job {
* Clear request queues and stop current request.
*/
public void clearQueue() {
if (getState() != Job.NONE) {
displaySizesComputed.set(false);
selectedQueue.clear();
backgroundQueue.clear();
requeueRequest.set(false);
stopComputeSize.set(true);
}
sizeQueue.clear();
displayQueue.clear();
}
/*
@ -419,52 +649,30 @@ public class SizeJob extends Job {
ArchiveConfigManager manager = ArchiveConfigManager.getInstance();
updateDisplayTimer();
mainLoop: while (!shutdown.get()) {
DisplayData displayData = null;
synchronized (this) {
if (!displaySizesComputed.get()) {
// Get sizes for the current display.
List<DisplayData> displayDatas = archiveInfoMap
.get(displayArchive).get(displayCategory)
.getDisplayDataList();
for (DisplayData dd : displayDatas) {
if (dd.getSize() == DisplayData.UNKNOWN_SIZE) {
displayData = dd;
break;
}
}
displaySizesComputed.set(displayData == null);
}
currentDisplayData = sizeQueue.peek();
if (currentDisplayData == null) {
break mainLoop;
}
if (displayData == null) {
if (!selectedQueue.isEmpty()) {
displayData = selectedQueue.remove();
} else if (!backgroundQueue.isEmpty()) {
displayData = backgroundQueue.remove();
}
// System.out.println("+++SizeJob: " + currentDisplayData);
if (displayData == null) {
break mainLoop;
} else if (displayData.getSize() >= 0) {
continue mainLoop;
}
}
stopComputeSize.set(false);
List<File> files = manager.getDisplayFiles(displayData, startCal,
endCal);
List<File> files = manager.getDisplayFiles(currentDisplayData,
startCal, endCal);
// Size no longer needed.
if (stopComputeSize.get()) {
if (requeueRequest.get()) {
requeue(displayData);
}
if (currentDisplayData != sizeQueue.peek()) {
// System.out.println("---SizeJob: " + currentDisplayData);
continue mainLoop;
}
long size = 0L;
peekCnt = peekFrequency;
stopComputeSize = false;
for (File file : files) {
if (file.isDirectory()) {
size += sizeOfDirectory(file);
@ -473,23 +681,19 @@ public class SizeJob extends Job {
}
// Skip when size no longer needed.
if (stopComputeSize.get()) {
if (requeueRequest.get()) {
requeue(displayData);
}
if (stopComputeSize) {
// System.out.println("---SizeJob: " + currentDisplayData);
continue mainLoop;
}
}
displayData.setSize(size);
List<DisplayData> list = new ArrayList<DisplayData>(1);
list.add(displayData);
for (IUpdateListener listener : listeners) {
listener.update(list);
}
sizeQueue.remove(currentDisplayData);
currentDisplayData.setSize(size);
displayQueue.add(currentDisplayData);
}
// System.out.println("xxxSizeJob: OK_STATUS");
shutdownDisplayTimer.set(true);
return Status.OK_STATUS;
}
@ -503,9 +707,18 @@ public class SizeJob extends Job {
private long sizeOfDirectory(File directory) {
long size = 0;
for (File file : directory.listFiles()) {
if (stopComputeSize.get()) {
if (stopComputeSize) {
break;
}
if (--peekCnt == 0) {
if (currentDisplayData != sizeQueue.peek()) {
// Forces break out of recursion.
stopComputeSize = true;
break;
}
peekCnt = peekFrequency;
}
if (file.isDirectory()) {
size += sizeOfDirectory(file);
} else {
@ -515,6 +728,44 @@ public class SizeJob extends Job {
return size;
}
/**
* Start timer to update GUI's display form data on the display Queue.
*/
private void updateDisplayTimer() {
if (displayTimer != null) {
displayTimer.cancel();
}
shutdownDisplayTimer.set(false);
displayTimer = new Timer();
TimerTask updateDisplayTask = new TimerTask() {
@Override
public void run() {
if (!displayQueue.isEmpty()) {
List<DisplayData> list = new ArrayList<DisplayData>(
displayQueue.size());
displayQueue.drainTo(list);
// for (DisplayData displayData : list) {
// System.out.println("== " + displayData);
// }
//
for (IUpdateListener listener : listeners) {
listener.update(list);
}
} else if (shutdownDisplayTimer.get()) {
// System.out.println("xxx updateDisplayTimer canceled");
displayTimer.cancel();
displayTimer = null;
}
}
};
displayTimer.schedule(updateDisplayTask, 1000, 2000);
}
/*
* (non-Javadoc)
*
@ -522,9 +773,125 @@ public class SizeJob extends Job {
*/
@Override
protected void canceling() {
selectedQueue.clear();
backgroundQueue.clear();
// System.err.println("canceling SizeJob");
clearQueue();
missingDataQueue.clear();
missingDataJob.cancel();
shutdown.set(true);
stopComputeSize.set(true);
}
/**
* Class used by the missing data job to obtain display data for given
* archive/category off the UI thread.
*/
private static class MissingData {
protected final String archive;
protected final String category;
protected final List<String> selectedList;
protected boolean visiable = false;
public MissingData(String archive, String category,
List<String> selectedList) {
this.archive = archive;
this.category = category;
this.selectedList = new ArrayList<String>(selectedList);
}
public boolean isSelected() {
return !selectedList.isEmpty();
}
public void setVisiable(boolean state) {
this.visiable = state;
}
public void setSelectedList(List<String> selectedList) {
this.selectedList.clear();
this.selectedList.addAll(selectedList);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("MissingData[");
sb.append("archive: ").append(archive);
sb.append(", category: ").append(category);
sb.append(", visible: ").append(visiable);
sb.append(", isSelected: ").append(isSelected());
sb.append("]");
return sb.toString();
}
}
/**
* This handles getting the display data in the missing data queue and
* queuing the results for the size job.
*/
private class MissingDataJob extends Job {
private final AtomicBoolean shutdown = new AtomicBoolean(false);
protected MissingData currentMissingData = null;
public MissingDataJob() {
super("MissingData");
}
@Override
protected IStatus run(IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return Status.OK_STATUS;
}
ArchiveConfigManager manager = ArchiveConfigManager.getInstance();
while (!shutdown.get()) {
synchronized (missingDataQueue) {
if (currentMissingData != null) {
missingDataQueue.notifyAll();
}
currentMissingData = missingDataQueue.poll();
}
if (currentMissingData == null) {
break;
}
String archiveName = currentMissingData.archive;
String categoryName = currentMissingData.category;
// System.out.println("== missingData: " + currentMissingData);
List<String> selectedList = currentMissingData.selectedList;
List<DisplayData> displayDatas = manager.getDisplayData(
archiveName, categoryName, false);
if (shutdown.get()) {
break;
}
for (DisplayData displayData : displayDatas) {
displayData.setSelected(selectedList.contains(displayData
.getDisplayLabel()));
sizeQueue.add(displayData);
}
archiveInfoMap.get(archiveName).get(categoryName)
.setDisplayDataList(displayDatas);
if (SizeJob.this.getState() == Job.NONE) {
SizeJob.this.schedule();
}
}
// System.out.println("xxx missingData");
return Status.OK_STATUS;
}
@Override
protected void canceling() {
// System.err.println("canceling MissingDataJob");
shutdown.set(true);
}
}
}

View file

@ -24,10 +24,6 @@ import java.util.Calendar;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
@ -48,12 +44,12 @@ import com.raytheon.uf.common.archive.config.ArchiveConfigManager;
import com.raytheon.uf.common.archive.config.ArchiveConstants;
import com.raytheon.uf.common.archive.config.CategoryConfig;
import com.raytheon.uf.common.archive.config.DisplayData;
import com.raytheon.uf.common.archive.config.SelectConfig;
import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException;
import com.raytheon.uf.common.util.SizeUtil;
import com.raytheon.uf.viz.archive.data.ArchiveInfo;
import com.raytheon.uf.viz.archive.data.CategoryInfo;
import com.raytheon.uf.viz.archive.data.IArchiveTotals;
import com.raytheon.uf.viz.archive.data.IRetentionHour;
import com.raytheon.uf.viz.archive.data.IUpdateListener;
import com.raytheon.uf.viz.archive.data.SizeJob;
import com.raytheon.uf.viz.core.VizApp;
@ -82,7 +78,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
*/
public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
IArchiveTotals, IUpdateListener, IModifyListener {
IArchiveTotals, IUpdateListener, IModifyListener, IRetentionHour {
/** Table composite that holds the table controls. */
private ArchiveTableComp tableComp;
@ -154,23 +150,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
super(parentShell, style, caveStyle);
}
public List<DisplayData> getAllSelected() {
List<DisplayData> allSelected = new ArrayList<DisplayData>();
for (String archiveName : sizeJob.getArchiveNames()) {
ArchiveInfo archiveInfo = sizeJob.get(archiveName);
for (String categoryName : archiveInfo.getCategoryNames()) {
CategoryInfo categoryInfo = archiveInfo.get(categoryName);
for (DisplayData displayData : categoryInfo
.getDisplayDataList()) {
if (displayData.isSelected()) {
allSelected.add(displayData);
}
}
}
}
return allSelected;
}
/**
* @return the name of the currently selected archive in the dialog; null if
* none found
@ -312,37 +291,12 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
protected void preOpened() {
super.preOpened();
setCursorBusy(true);
populateComboBoxes();
String titleName = initDisplayData();
setSelectName(titleName);
populateTableComp();
setCursorBusy(false);
// Setup to display blank dialog with busy cursor while getting data.
Job job = new Job("setup") {
@Override
protected IStatus run(IProgressMonitor monitor) {
if (!shell.isDisposed()) {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
populateComboBoxes();
}
});
}
final String titleName = initDisplayData(null);
if (!shell.isDisposed()) {
VizApp.runAsync(new Runnable() {
@Override
public void run() {
setSelectName(titleName);
updateTableComp();
setCursorBusy(false);
}
});
}
return Status.OK_STATUS;
}
};
job.schedule();
addModifiedListener(this);
shell.addShellListener(new ShellAdapter() {
@ -447,7 +401,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
categoryCbo.add(categoryName);
}
categoryCbo.select(0);
categoryComboSelection();
}
/**
@ -461,40 +414,13 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
* Set up all display data and queue getting sizes for any that are
* selected.
*/
protected String initDisplayData(String selectName) {
String fileName = ArchiveConstants.selectFileName(type, selectName);
SelectConfig selections = manager.loadSelection(fileName);
if (selections == null) {
selections = new SelectConfig();
selections.setName(ArchiveConstants.defaultSelectName);
}
setRetentionTimes(selections.getStarRetentionHours());
String[] archiveNames = manager.getArchiveDataNamesList();
for (String archiveName : archiveNames) {
ArchiveInfo archiveInfo = new ArchiveInfo();
String[] categoryNames = manager.getCategoryNames(manager
.getArchive(archiveName));
for (String categoryName : categoryNames) {
// TODO future enhancement to make GUI display faster need to
// move getting displayDatas into SizeJob then get current
// display, displays with selections then other displays in the
// background.
List<String> selectedList = selections.getSelectedList(
archiveName, categoryName);
List<DisplayData> displayDatas = manager.getDisplayData(
archiveName, categoryName, false);
CategoryInfo categoryInfo = new CategoryInfo(archiveName,
categoryName, displayDatas);
archiveInfo.add(categoryInfo);
for (DisplayData displayData : displayDatas) {
displayData.setSelected(selectedList.contains(displayData
.getDisplayLabel()));
}
}
sizeJob.put(archiveName, archiveInfo);
}
protected String initDisplayData() {
String displayArchive = getSelectedArchiveName();
String displayCategory = getSelectedCategoryName();
String selectedName = sizeJob.initData(type, null, displayArchive,
displayCategory, this);
sizeJob.resetTime(getStart(), getEnd());
return selections.getName();
return selectedName;
}
/**
@ -534,23 +460,14 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
try {
setShowingSelected(false);
ArchiveInfo archiveInfo = sizeJob.get(archiveName);
// Not yet populated by background job.
if (archiveInfo == null) {
return;
List<DisplayData> displayDatas = sizeJob.changeDisplay(archiveName,
categoryName);
if (displayDatas != null) {
tableComp
.populateTable(archiveName, categoryName, displayDatas);
} else {
tableComp.refresh();
}
// Not yet populated by background job.
CategoryInfo categoryInfo = archiveInfo.get(categoryName);
if (categoryInfo == null) {
return;
}
sizeJob.changeDisplayQueue(archiveName, categoryName);
tableComp.populateTable(archiveName, categoryName,
categoryInfo.getDisplayDataList());
} finally {
setCursorBusy(false);
}
@ -643,22 +560,24 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
}
/**
* Sets the state fo the showing selected flag and updates the label for the
* show selected button.
* Sets the state for the showing selected flag and updates the label for
* the show selected button.
*
* @param state
*/
private void setShowingSelected(boolean state) {
if (showingSelected != state) {
showingSelected = state;
if (showingSelected) {
showSelectedBtn.setText(" Category ");
showSelectedBtn
.setToolTipText("Change display to show category.");
} else {
showSelectedBtn.setText(" Selected ");
showSelectedBtn
.setToolTipText("Change display to show all case selections");
if (showSelectedBtn != null && !showSelectedBtn.isDisposed()) {
if (showingSelected != state) {
showingSelected = state;
if (showingSelected) {
showSelectedBtn.setText(" Category ");
showSelectedBtn
.setToolTipText("Change display to show category.");
} else {
showSelectedBtn.setText(" Selected ");
showSelectedBtn
.setToolTipText("Change display to show all case selections");
}
}
}
}
@ -671,10 +590,11 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
try {
setShowingSelected(true);
List<DisplayData> slectedData = sizeJob.getSelectAll();
List<DisplayData> selectedData = sizeJob.changeDisplayAll();
tableComp.populateSelectAll(slectedData);
sizeJob.changeDisplayQueue(null, null);
if (selectedData != null) {
tableComp.populateSelectAll(selectedData);
}
} finally {
setCursorBusy(false);
}
@ -735,20 +655,7 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
* @return selectedDatas
*/
protected List<DisplayData> getSelectedData() {
List<DisplayData> selectedDatas = new ArrayList<DisplayData>();
for (String archiveName : sizeJob.getArchiveNames()) {
ArchiveInfo archiveInfo = sizeJob.get(archiveName);
for (String categoryName : archiveInfo.getCategoryNames()) {
CategoryInfo categoryInfo = archiveInfo.get(categoryName);
for (DisplayData displayData : categoryInfo
.getDisplayDataList()) {
if (displayData.isSelected()) {
selectedDatas.add(displayData);
}
}
}
}
return selectedDatas;
return sizeJob.getSelectAll();
}
/**
@ -773,7 +680,7 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
*
* @param startTimeOffset
*/
protected void setRetentionTimes(long startTimeOffset) {
public void setRetentionTimes(long startTimeOffset) {
// do nothing override by sub-classes
}

View file

@ -61,6 +61,7 @@ import com.raytheon.uf.viz.archive.data.SizeJob;
* May 23, 2013 #1964 lvenable Initial creation
* Jul 24, 2013 #2221 rferrel Changes for select configuration.
* Aug 06, 2013 #2222 rferrel Changes to display all selected data.
* Aug 14, 2013 #2220 rferrel Add refresh method.
*
* </pre>
*
@ -479,6 +480,7 @@ public class ArchiveTableComp extends Composite {
private void populateTable(List<DisplayData> displayDatas) {
tableData = displayDatas.toArray(new DisplayData[0]);
Arrays.sort(tableData, DisplayData.LABEL_ORDER);
table.removeAll();
table.setItemCount(tableData.length);
@ -493,6 +495,13 @@ public class ArchiveTableComp extends Composite {
table.clearAll();
}
/**
* Update the current tables display.
*/
public void refresh() {
table.clearAll();
}
/**
* Check the modified state and inform listeners when it changes.
*/

View file

@ -262,7 +262,7 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
* com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#setRetentionTimes(long)
*/
@Override
protected void setRetentionTimes(long startRetentionHours) {
public void setRetentionTimes(long startRetentionHours) {
long startTimeOffset = startRetentionHours * TimeUtil.MILLIS_PER_HOUR;
endDate = TimeUtil.newDate();
long time = endDate.getTime();
@ -847,6 +847,7 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
if (!startDate.equals(date)) {
startDate = date;
sizeJob.resetTime(getStart(), getEnd());
modified();
}
} else {
if (date.before(startDate)) {
@ -860,6 +861,7 @@ public class CaseCreationDlg extends AbstractArchiveDlg {
if (!endDate.equals(date)) {
endDate = date;
sizeJob.resetTime(getStart(), getEnd());
modified();
}
}

View file

@ -714,9 +714,10 @@ public class ArchiveConfigManager {
displayData = new DisplayData(archiveConfig,
categoryConfig, dataSet, displayLabel);
displays.put(displayLabel, displayData);
} else {
} else if (!displayData.dataSets.contains(dataSet)) {
displayData.dataSets.add(dataSet);
}
displayData.dirsMap.put(dataSet, displayDirs);
break;
}

View file

@ -23,6 +23,7 @@ import com.raytheon.uf.common.util.SizeUtil;
* Jun 7, 2013 1966 rferrel Initial creation
* Aug 02, 2013 2224 rferrel Changes to include DataSet in configuration.
* Aug 06, 2013 2222 rferrel Changes to display all selected data.
* Aug 14, 2013 2220 rferrel Add priority comparator.
*
* </pre>
*
@ -63,6 +64,24 @@ public class DisplayData implements Comparable<DisplayData> {
}
};
/** Comparator for priority ordering for priority queue. */
public static final Comparator<DisplayData> PRIORITY_ORDER = new Comparator<DisplayData>() {
@Override
public int compare(DisplayData o1, DisplayData o2) {
if (o1.visible != o2.visible) {
return o1.visible ? -1 : +1;
} else if (o1.visible) {
return LABEL_ORDER.compare(o1, o2);
}
if (o1.selected != o2.selected) {
return o1.selected ? -1 : +1;
}
return LABEL_ORDER.compare(o1, o2);
}
};
/** Label to use when size not yet known. */
public static final String UNKNOWN_SIZE_LABEL = "????";
@ -93,9 +112,11 @@ public class DisplayData implements Comparable<DisplayData> {
private boolean selected = false;
/**
* For use by GUI for indicating the size of the display label's row
* contents.
* Indicates data is visible in the display.
*/
private boolean visible = false;
/** For use by GUI for indicating the size of the directories' contents. */
private long size = UNKNOWN_SIZE;
/**
@ -133,6 +154,14 @@ public class DisplayData implements Comparable<DisplayData> {
this.selected = selected;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
/**
*
* @return displayLabel.
@ -263,6 +292,7 @@ public class DisplayData implements Comparable<DisplayData> {
public String toString() {
StringBuilder sb = new StringBuilder("DisplayData[");
sb.append("displayLabel: ").append(displayLabel);
sb.append(", isVisible: ").append(isVisible());
sb.append(", isSlected: ").append(isSelected());
sb.append(", size: ").append(size);
sb.append(", category.name: ").append(categoryConfig.getName());