Omaha #5314: Fix issues with alert viz system log when purge runs.

Change-Id: I118e064ed9e4190ae2516938f7a6b50dc5f724ac

Former-commit-id: a7ae41eac4a570a7d8362358e548caed63e655ee
This commit is contained in:
David Gillingham 2016-02-23 12:50:02 -06:00
parent e14f2ed6a3
commit 67d39d8440
7 changed files with 152 additions and 85 deletions

View file

@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
com.raytheon.uf.common.localization,
com.raytheon.uf.common.message;bundle-version="1.11.11",
com.raytheon.uf.viz.alertviz;bundle-version="1.11.11"
com.raytheon.uf.viz.alertviz;bundle-version="1.11.11",
org.apache.commons.lang3;bundle-version="3.4.0"
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.viz.alertviz.ui,
com.raytheon.uf.viz.alertviz.ui.audio,

View file

@ -25,7 +25,9 @@ import java.io.StringWriter;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import org.apache.commons.lang3.ArrayUtils;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
@ -57,12 +59,15 @@ import com.raytheon.uf.viz.alertviz.AlertvizException;
import com.raytheon.uf.viz.alertviz.AlertvizJob;
import com.raytheon.uf.viz.alertviz.Container;
import com.raytheon.uf.viz.alertviz.IAlertArrivedCallback;
import com.raytheon.uf.viz.alertviz.IAlertVizLogPurgedNotifier;
import com.raytheon.uf.viz.alertviz.LogUtil;
import com.raytheon.uf.viz.alertviz.LogUtil.Order;
import com.raytheon.uf.viz.alertviz.PurgeLogJob;
import com.raytheon.uf.viz.alertviz.SystemStatusHandler;
import com.raytheon.uf.viz.alertviz.config.AlertMetadata;
import com.raytheon.uf.viz.alertviz.config.Category;
import com.raytheon.uf.viz.alertviz.config.TrayConfiguration;
import com.raytheon.uf.viz.core.VizApp;
/**
* Implements a basic log viewer capability
@ -84,7 +89,8 @@ import com.raytheon.uf.viz.alertviz.config.TrayConfiguration;
* @version 1.0
*/
public class SimpleLogViewer implements IAlertArrivedCallback {
public class SimpleLogViewer implements IAlertArrivedCallback,
IAlertVizLogPurgedNotifier {
private Display display;
@ -366,6 +372,7 @@ public class SimpleLogViewer implements IAlertArrivedCallback {
showHideLog();
AlertvizJob.getInstance().addAlertArrivedCallback(this);
PurgeLogJob.getInstance().addLogPurgeListener(this);
shell.open();
@ -382,6 +389,7 @@ public class SimpleLogViewer implements IAlertArrivedCallback {
}
}
PurgeLogJob.getInstance().removeLogPurgeListener(this);
AlertvizJob.getInstance().removeAlertArrivedCallback(this);
table.dispose();
red.dispose();
@ -441,4 +449,23 @@ public class SimpleLogViewer implements IAlertArrivedCallback {
ErrorDialog.openError(parentShell, dialogTitle, msg, ms);
}
@Override
public void recordsPurged(final Collection<Integer> recordsDeleted) {
VizApp.runSync(new Runnable() {
@Override
public void run() {
Collection<Integer> tableItemsToDelete = new HashSet<>();
for (int i = 0; i < table.getItemCount(); i++) {
TableItem tableItem = table.getItem(i);
if (recordsDeleted.contains(tableItem.getData())) {
tableItemsToDelete.add(Integer.valueOf(i));
}
}
table.remove(ArrayUtils.toPrimitive(tableItemsToDelete
.toArray(new Integer[0])));
}
});
}
}

View file

@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.ui,
ch.qos.logback;bundle-version="1.0.13",
org.slf4j;bundle-version="1.7.5",
org.apache.derby;bundle-version="10.10.1",
com.raytheon.uf.common.logback;bundle-version="1.15.0"
com.raytheon.uf.common.logback;bundle-version="1.15.0",
com.raytheon.uf.common.time;bundle-version="1.15.0"
Export-Package: com.raytheon.uf.viz.alertviz,
com.raytheon.uf.viz.alertviz.config
Bundle-RequiredExecutionEnvironment: JavaSE-1.7

View file

@ -39,7 +39,6 @@ import com.raytheon.uf.viz.alertviz.config.Configuration;
import com.raytheon.uf.viz.alertviz.config.ForcedConfiguration;
import com.raytheon.uf.viz.alertviz.config.Source;
import com.raytheon.uf.viz.alertviz.internal.LogMessageDAO;
import com.raytheon.uf.viz.alertviz.internal.PurgeLogJob;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
@ -58,6 +57,7 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
* Jul 27, 2015 4654 skorolev Added a localization level filtration
* Sep 21, 2015 4654 njensen Made filter logic strict instead of eager
* Jan 14, 2016 5054 randerso Remove dummy shell
* Feb 23, 2016 5314 dgilling Support changes to PurgeLogJob.
*
* </pre>
*
@ -104,7 +104,7 @@ public class Container implements IConfigurationChangedListener {
.getForcedConfiguration();
ConfigurationManager.getInstance().addListener(this);
this.callbacks = callbacks;
PurgeLogJob archive = new PurgeLogJob();
PurgeLogJob archive = PurgeLogJob.getInstance();
archive.schedule();
}

View file

@ -0,0 +1,52 @@
/**
* 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.alertviz;
import java.util.Collection;
/**
* Listener interface for classes that would like to be notified when records
* are purged from the alert viz internal message store. Provides a collection
* containing the primary keys of all purged records.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Feb 22, 2016 #5314 dgilling Initial creation
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public interface IAlertVizLogPurgedNotifier {
/**
* Callback for this listener.
*
* @param recordsDeleted
* The primary keys of all records purged
*/
void recordsPurged(Collection<Integer> recordsDeleted);
}

View file

@ -17,9 +17,11 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertviz.internal;
package com.raytheon.uf.viz.alertviz;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@ -28,9 +30,8 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.widgets.Display;
import com.raytheon.uf.viz.alertviz.Activator;
import com.raytheon.uf.viz.alertviz.AlertvizException;
import com.raytheon.uf.viz.alertviz.Constants;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.alertviz.internal.LogMessageDAO;
/**
* Purges old database entries.
@ -41,6 +42,7 @@ import com.raytheon.uf.viz.alertviz.Constants;
* ------------ ---------- ----------- --------------------------
* Sep 22, 2008 1433 chammack Initial creation
* Aug 04, 2014 3356 njensen Added e.printStacktrace() to trace errors
* Feb 23, 2016 5314 dgilling Rewrite as singleton, add listeners.
*
* </pre>
*
@ -49,20 +51,30 @@ import com.raytheon.uf.viz.alertviz.Constants;
*/
public class PurgeLogJob extends Job {
private int ageOfLogInHours;
private static final int DEFAULT_AGE_OF_LOG_IN_HRS = 12;
private static final int MILLISECONDS_IN_HOUR = 60 * 60 * 1000;
private static final long JOB_CYCLE_TIME = 1 * TimeUtil.MILLIS_PER_HOUR;
public PurgeLogJob() {
private static final PurgeLogJob INSTANCE = new PurgeLogJob();
private final Collection<IAlertVizLogPurgedNotifier> purgeListeners;
private final int ageOfLogInHours;
public static PurgeLogJob getInstance() {
return INSTANCE;
}
private PurgeLogJob() {
super("Archive Log Purge");
setSystem(true);
ageOfLogInHours = Activator.getDefault().getPreferenceStore()
this.purgeListeners = new CopyOnWriteArraySet<>();
int configuredLogAge = Activator.getDefault().getPreferenceStore()
.getInt(Constants.P_MAX_AGE_OF_LOGS);
if (ageOfLogInHours == 0) {
this.ageOfLogInHours = DEFAULT_AGE_OF_LOG_IN_HRS;
}
this.ageOfLogInHours = (configuredLogAge != 0) ? configuredLogAge
: DEFAULT_AGE_OF_LOG_IN_HRS;
this.schedule();
@ -70,17 +82,14 @@ public class PurgeLogJob extends Job {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
Timestamp date = LogMessageDAO.getInstance().getLastPurgeTime();
long lastPurgeInMs = date.getTime();
long now = System.currentTimeMillis();
if ((now - lastPurgeInMs) > (ageOfLogInHours * MILLISECONDS_IN_HOUR)) {
Timestamp ts = new Timestamp(now
- (ageOfLogInHours * MILLISECONDS_IN_HOUR));
LogMessageDAO.getInstance().purge(ts);
}
Timestamp ts = new Timestamp(now
- (ageOfLogInHours * TimeUtil.MILLIS_PER_HOUR));
Collection<Integer> recordsDeleted = LogMessageDAO.getInstance()
.purge(ts);
firePurgeListeners(recordsDeleted);
} catch (AlertvizException e) {
final Status s = new Status(Status.ERROR, Activator.PLUGIN_ID,
"Error occurred during purge and rotate", e);
@ -98,8 +107,22 @@ public class PurgeLogJob extends Job {
}
this.schedule(ageOfLogInHours * MILLISECONDS_IN_HOUR);
this.schedule(JOB_CYCLE_TIME);
return Status.OK_STATUS;
}
public void addLogPurgeListener(IAlertVizLogPurgedNotifier listener) {
purgeListeners.add(listener);
}
public void removeLogPurgeListener(IAlertVizLogPurgedNotifier listener) {
purgeListeners.remove(listener);
}
private void firePurgeListeners(Collection<Integer> recordsDeleted) {
for (IAlertVizLogPurgedNotifier listener : purgeListeners) {
listener.recordsPurged(recordsDeleted);
}
}
}

View file

@ -30,7 +30,10 @@ import java.sql.Statement;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import com.raytheon.uf.common.message.StatusMessage;
@ -59,18 +62,12 @@ import com.raytheon.uf.viz.core.localization.LocalizationManager;
public class LogMessageDAO {
private static final int VERSION = 1;
private static final String SELECT_ALL_QUERY = "SELECT event_time, category, priority, message, details, source, pk, acknowledgedBy, acknowledgedAt FROM log";
private static final String SELECT_ALL_QUERY_BY_PK = "SELECT event_time, category, priority, message, details, source, pk, acknowledgedBy, acknowledgedAt FROM log WHERE pk = ?";
private static final String SELECT_ALL_QUERY_BY_ROW_OFFSET = "SELECT event_time, category, priority, message, details, source, pk, acknowledgedBy, acknowledgedAt FROM log ORDER BY pk OFFSET ? ROWS FETCH NEXT ROW ONLY";
private static final String PURGE_TIME_QUERY = "SELECT purge_time FROM dbMetadata";
private static final String PURGE_TIME_UPDATE = "UPDATE dbMetadata SET purge_time = ?";
private static final String MESSAGE_COUNT_QUERY = "SELECT COUNT(pk) FROM log";
private static final String SELECT_ALL_BY_DATE_AND_SOURCE_AFTER = "SELECT event_time, category, priority, message, details, source, pk, acknowledgedBy, acknowledgedAt FROM log WHERE event_time > ?";
@ -83,17 +80,10 @@ public class LogMessageDAO {
private static final String DB_CREATE = "CREATE TABLE log(pk INT NOT NULL GENERATED BY DEFAULT AS IDENTITY, event_time TIMESTAMP, category VARCHAR(64), source VARCHAR(64), priority INT, message VARCHAR(32672), details VARCHAR(32672), acknowledgedBy VARCHAR(32), acknowledgedAt TIMESTAMP)";
private static final String PURGE_STATEMENT = "DELETE FROM log WHERE event_time < ?";
private static final String METADATA_CREATE = "CREATE TABLE dbMetadata(purge_time TIMESTAMP, version INT)";
private static final String PURGE_SELECT_STATEMENT = "SELECT pk FROM log WHERE event_time < ?";
private static final String ACKNOWLEDGE = "UPDATE log SET acknowledgedAt = ? , acknowledgedBy = ? WHERE pk = ?";
private static final String METADATA_INSERT = "INSERT INTO dbMetadata(version, purge_time) values("
+ VERSION
+ ",'"
+ new Timestamp(System.currentTimeMillis()).toString() + "')";
private Connection connection;
private PreparedStatement saveStatement;
@ -182,8 +172,6 @@ public class LogMessageDAO {
if (needCreation) {
statement = connection.createStatement();
statement.execute(DB_CREATE);
statement.execute(METADATA_CREATE);
statement.execute(METADATA_INSERT);
}
connection.commit();
} catch (Exception e1) {
@ -492,28 +480,29 @@ public class LogMessageDAO {
}
}
public void purge(Timestamp filter) throws AlertvizException {
PreparedStatement statement = null;
PreparedStatement updateStatement = null;
public Collection<Integer> purge(Timestamp filter) throws AlertvizException {
boolean errorOccurred = false;
try {
Connection conn = getConnection();
statement = conn.prepareStatement(PURGE_STATEMENT);
statement.setTimestamp(1, filter);
statement.executeUpdate();
Connection conn = getConnection();
updateStatement = conn.prepareStatement(PURGE_TIME_UPDATE);
updateStatement.setTimestamp(1,
new Timestamp(System.currentTimeMillis()));
updateStatement.executeUpdate();
conn.commit();
return;
try (PreparedStatement purgeSelect = conn.prepareStatement(
PURGE_SELECT_STATEMENT, ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE)) {
purgeSelect.setTimestamp(1, filter);
try (ResultSet rs = purgeSelect.executeQuery()) {
Collection<Integer> deletedKeys = new HashSet<>(512, 1f);
while (rs.next()) {
deletedKeys.add(Integer.valueOf(rs.getInt(1)));
rs.deleteRow();
}
conn.commit();
return Collections.unmodifiableCollection(deletedKeys);
}
} catch (SQLException e) {
errorOccurred = true;
throw new AlertvizException("Error loading ", e);
throw new AlertvizException("Error purging ", e);
} finally {
closeStatement(statement);
closeStatement(updateStatement);
if (errorOccurred) {
closeConnection();
}
@ -553,32 +542,6 @@ public class LogMessageDAO {
return 0;
}
public Timestamp getLastPurgeTime() throws AlertvizException {
ResultSet rs = null;
Statement statement = null;
boolean errorOccurred = false;
try {
Connection conn = getConnection();
statement = conn.createStatement();
statement.setMaxFieldSize(1);
rs = statement.executeQuery(PURGE_TIME_QUERY);
if (rs.next()) {
return rs.getTimestamp("purge_time");
}
conn.commit();
return null;
} catch (SQLException e) {
errorOccurred = true;
throw new AlertvizException("Error getting last purge time ", e);
} finally {
closeResultSet(rs);
closeStatement(statement);
if (errorOccurred) {
closeConnection();
}
}
}
private StatusMessage[] reconstituteResults(ResultSet rs)
throws SQLException {
List<StatusMessage> retVal = new ArrayList<StatusMessage>();