/*
* Copyright (c) 2010-2015 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.schema.statistics;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.xml.ns._public.common.common_3.IterativeTaskInformationType;
import org.apache.commons.collections.buffer.CircularFifoBuffer;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author Pavol Mederly
*/
public class IterativeTaskInformation {
public static final int LAST_FAILURES_KEPT = 30;
/*
* Thread safety: Just like EnvironmentalPerformanceInformation, instances of this class may be accessed from
* more than one thread at once. Updates are invoked in the context of the thread executing the task.
* Queries are invoked either from this thread, or from some observer (task manager or GUI thread).
*/
protected final IterativeTaskInformationType startValue;
protected String lastSuccessObjectName;
protected String lastSuccessObjectDisplayName;
protected QName lastSuccessObjectType;
protected String lastSuccessObjectOid;
protected Date lastSuccessEndTimestamp;
protected long lastSuccessDuration;
protected long totalSuccessDuration;
protected int totalSuccessCount;
protected String lastFailureObjectName;
protected String lastFailureObjectDisplayName;
protected QName lastFailureObjectType;
protected String lastFailureObjectOid;
protected Date lastFailureEndTimestamp;
protected long lastFailureDuration;
protected long totalFailureDuration;
protected int totalFailureCount;
protected Throwable lastFailureException;
protected String lastFailureExceptionMessage;
protected String currentObjectName;
protected String currentObjectDisplayName;
protected QName currentObjectType;
protected String currentObjectOid;
protected Date currentObjectStartTimestamp;
protected CircularFifoBuffer lastFailures = new CircularFifoBuffer(LAST_FAILURES_KEPT);
public IterativeTaskInformation() {
this(null);
}
public IterativeTaskInformation(IterativeTaskInformationType value) {
startValue = value;
}
public IterativeTaskInformationType getStartValue() {
return startValue;
}
public synchronized IterativeTaskInformationType getDeltaValue() {
IterativeTaskInformationType rv = toIterativeTaskInformationType();
return rv;
}
public synchronized IterativeTaskInformationType getAggregatedValue() {
IterativeTaskInformationType delta = toIterativeTaskInformationType();
IterativeTaskInformationType rv = aggregate(startValue, delta);
return rv;
}
private IterativeTaskInformationType aggregate(IterativeTaskInformationType startValue, IterativeTaskInformationType delta) {
if (startValue == null) {
return delta;
}
IterativeTaskInformationType rv = new IterativeTaskInformationType();
addTo(rv, startValue, true);
addTo(rv, delta, true);
return rv;
}
private IterativeTaskInformationType toIterativeTaskInformationType() {
IterativeTaskInformationType rv = new IterativeTaskInformationType();
toJaxb(rv);
return rv;
}
public synchronized void recordOperationEnd(String objectName, String objectDisplayName, QName objectType, String objectOid, long started, Throwable exception) {
if (exception != null) {
lastFailureObjectName = objectName;
lastFailureObjectDisplayName = objectDisplayName;
lastFailureObjectType = objectType;
lastFailureObjectOid = objectOid;
lastFailureEndTimestamp = new Date();
lastFailureDuration = lastFailureEndTimestamp.getTime() - started;
lastFailureException = exception;
lastFailureExceptionMessage = exception.getClass().getSimpleName() + ": " + exception.getMessage();
totalFailureDuration += lastFailureDuration;
totalFailureCount++;
String name = objectName != null ? objectName
: objectOid != null ? objectOid : "(unnamed)";
lastFailures.add(name + ": " + exception.getMessage());
} else {
lastSuccessObjectName = objectName;
lastSuccessObjectDisplayName = objectDisplayName;
lastSuccessObjectType = objectType;
lastSuccessObjectOid = objectOid;
lastSuccessEndTimestamp = new Date();
lastSuccessDuration = lastSuccessEndTimestamp.getTime() - started;
totalSuccessDuration += lastSuccessDuration;
totalSuccessCount++;
}
currentObjectName = null;
currentObjectDisplayName = null;
currentObjectType = null;
currentObjectOid = null;
currentObjectStartTimestamp = null;
}
public synchronized void recordOperationStart(String objectName, String objectDisplayName, QName objectType, String objectOid) {
currentObjectName = objectName;
currentObjectDisplayName = objectDisplayName;
currentObjectType = objectType;
currentObjectOid = objectOid;
currentObjectStartTimestamp = new Date();
}
private void toJaxb(IterativeTaskInformationType rv) {
rv.setLastSuccessObjectName(lastSuccessObjectName);
rv.setLastSuccessObjectDisplayName(lastSuccessObjectDisplayName);
rv.setLastSuccessObjectType(lastSuccessObjectType);
rv.setLastSuccessObjectOid(lastSuccessObjectOid);
rv.setLastSuccessEndTimestamp(XmlTypeConverter.createXMLGregorianCalendar(lastSuccessEndTimestamp));
rv.setLastSuccessDuration(lastSuccessDuration);
rv.setTotalSuccessDuration(totalSuccessDuration);
rv.setTotalSuccessCount(totalSuccessCount);
rv.setLastFailureObjectName(lastFailureObjectName);
rv.setLastFailureObjectDisplayName(lastFailureObjectDisplayName);
rv.setLastFailureObjectType(lastFailureObjectType);
rv.setLastFailureObjectOid(lastFailureObjectOid);
rv.setLastFailureEndTimestamp(XmlTypeConverter.createXMLGregorianCalendar(lastFailureEndTimestamp));
rv.setLastFailureDuration(lastFailureDuration);
rv.setLastFailureExceptionMessage(lastFailureExceptionMessage);
rv.setTotalFailureDuration(totalFailureDuration);
rv.setTotalFailureCount(totalFailureCount);
rv.setCurrentObjectName(currentObjectName);
rv.setCurrentObjectDisplayName(currentObjectDisplayName);
rv.setCurrentObjectType(currentObjectType);
rv.setCurrentObjectOid(currentObjectOid);
rv.setCurrentObjectStartTimestamp(XmlTypeConverter.createXMLGregorianCalendar(currentObjectStartTimestamp));
}
// sum != null, delta != null
// overrideCurrent should be TRUE if the delta is chronologically later (i.e. if delta is meant as an update to sum)
// if it is simply an aggregation of various (parallel) sources, overrideCurrent should be FALSE
public static void addTo(IterativeTaskInformationType sum, IterativeTaskInformationType delta, boolean overrideCurrent) {
if (sum.getLastSuccessEndTimestamp() == null || (delta.getLastSuccessEndTimestamp() != null &&
delta.getLastSuccessEndTimestamp().compare(sum.getLastSuccessEndTimestamp()) == DatatypeConstants.GREATER)) {
sum.setLastSuccessObjectName(delta.getLastSuccessObjectName());
sum.setLastSuccessObjectDisplayName(delta.getLastSuccessObjectDisplayName());
sum.setLastSuccessObjectType(delta.getLastSuccessObjectType());
sum.setLastSuccessObjectOid(delta.getLastSuccessObjectOid());
sum.setLastSuccessEndTimestamp(delta.getLastSuccessEndTimestamp());
sum.setLastSuccessDuration(delta.getLastSuccessDuration());
}
sum.setTotalSuccessDuration(sum.getTotalSuccessDuration() + delta.getTotalSuccessDuration());
sum.setTotalSuccessCount(sum.getTotalSuccessCount() + delta.getTotalSuccessCount());
if (sum.getLastFailureEndTimestamp() == null || (delta.getLastFailureEndTimestamp() != null &&
delta.getLastFailureEndTimestamp().compare(sum.getLastFailureEndTimestamp()) == DatatypeConstants.GREATER)) {
sum.setLastFailureObjectName(delta.getLastFailureObjectName());
sum.setLastFailureObjectDisplayName(delta.getLastFailureObjectDisplayName());
sum.setLastFailureObjectType(delta.getLastFailureObjectType());
sum.setLastFailureObjectOid(delta.getLastFailureObjectOid());
sum.setLastFailureEndTimestamp(delta.getLastFailureEndTimestamp());
sum.setLastFailureDuration(delta.getLastFailureDuration());
sum.setLastFailureExceptionMessage(delta.getLastFailureExceptionMessage());
}
sum.setTotalFailureDuration(sum.getTotalFailureDuration() + delta.getTotalFailureDuration());
sum.setTotalFailureCount(sum.getTotalFailureCount() + delta.getTotalFailureCount());
if (overrideCurrent || sum.getCurrentObjectStartTimestamp() == null || (delta.getCurrentObjectStartTimestamp() != null &&
delta.getCurrentObjectStartTimestamp().compare(sum.getCurrentObjectStartTimestamp()) == DatatypeConstants.GREATER)) {
sum.setCurrentObjectName(delta.getCurrentObjectName());
sum.setCurrentObjectDisplayName(delta.getCurrentObjectDisplayName());
sum.setCurrentObjectType(delta.getCurrentObjectType());
sum.setCurrentObjectOid(delta.getCurrentObjectOid());
sum.setCurrentObjectStartTimestamp(delta.getCurrentObjectStartTimestamp());
}
}
public List<String> getLastFailures() {
return new ArrayList<>(lastFailures);
}
}