/*******************************************************************************
* Copyright (c) 2012-2015 INRIA.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Generoso Pagano - initial API and implementation
******************************************************************************/
package fr.inria.soctrace.lib.storage.visitors;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import fr.inria.soctrace.lib.model.AnalysisResult;
import fr.inria.soctrace.lib.model.AnalysisResultAnnotationData;
import fr.inria.soctrace.lib.model.AnalysisResultData.AnalysisResultType;
import fr.inria.soctrace.lib.model.AnalysisResultGroupData;
import fr.inria.soctrace.lib.model.AnalysisResultGroupData.DepthFirstIterator;
import fr.inria.soctrace.lib.model.AnalysisResultSearchData;
import fr.inria.soctrace.lib.model.Annotation;
import fr.inria.soctrace.lib.model.AnnotationParam;
import fr.inria.soctrace.lib.model.AnnotationParamType;
import fr.inria.soctrace.lib.model.AnnotationType;
import fr.inria.soctrace.lib.model.Event;
import fr.inria.soctrace.lib.model.EventParam;
import fr.inria.soctrace.lib.model.EventParamType;
import fr.inria.soctrace.lib.model.EventProducer;
import fr.inria.soctrace.lib.model.EventType;
import fr.inria.soctrace.lib.model.File;
import fr.inria.soctrace.lib.model.Group;
import fr.inria.soctrace.lib.model.Group.LeafMapping;
import fr.inria.soctrace.lib.model.OrderedGroup;
import fr.inria.soctrace.lib.model.utils.SoCTraceException;
import fr.inria.soctrace.lib.storage.TraceDBObject;
import fr.inria.soctrace.lib.storage.utils.SQLConstants;
import fr.inria.soctrace.lib.storage.utils.SQLConstants.FramesocTable;
import fr.inria.soctrace.lib.utils.SoctraceUtils;
/**
* Visitor able to update the entities of the trace DB.
*
* @author "Generoso Pagano <generoso.pagano@inria.fr>"
*
*/
public class TraceDBUpdateVisitor extends ModelVisitor {
/**
* DB object related to this visitor
*/
private TraceDBObject traceDB;
/**
* The constructor.
*
* @param traceDB
* trace database object
* @throws SoCTraceException
*/
public TraceDBUpdateVisitor(TraceDBObject traceDB) throws SoCTraceException {
super();
this.traceDB = traceDB;
try {
Connection conn = traceDB.getConnection();
PreparedStatementDescriptor psd = null;
// Raw trace
// Events
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_UPDATE),
FramesocTable.EVENT);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_TYPE_UPDATE),
FramesocTable.EVENT_TYPE);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_PARAM_UPDATE),
FramesocTable.EVENT_PARAM);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_PARAM_TYPE_UPDATE),
FramesocTable.EVENT_PARAM_TYPE);
addDescriptor(psd);
// Event Producers
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_EVENT_PRODUCER_UPDATE),
FramesocTable.EVENT_PRODUCER);
addDescriptor(psd);
// File
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_FILE_UPDATE),
FramesocTable.FILE);
addDescriptor(psd);
// Analysis results
// Analysis Result
postClearBatches();
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANALYSIS_RESULT_UPDATE),
FramesocTable.ANALYSIS_RESULT);
addDescriptor(psd);
// Search
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_SEARCH_UPDATE),
FramesocTable.SEARCH);
addDescriptor(psd);
// Annotation
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_UPDATE),
FramesocTable.ANNOTATION);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_TYPE_UPDATE),
FramesocTable.ANNOTATION_TYPE);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_PARAM_UPDATE),
FramesocTable.ANNOTATION_PARAM);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_ANNOTATION_PARAM_TYPE_UPDATE),
FramesocTable.ANNOTATION_PARAM_TYPE);
addDescriptor(psd);
// Group
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_GROUP_UPDATE),
FramesocTable.ENTITY_GROUP);
addDescriptor(psd);
psd = new PreparedStatementDescriptor(
conn.prepareStatement(SQLConstants.PREPARED_STATEMENT_GROUP_MAPPING_UPDATE),
FramesocTable.GROUP_MAPPING);
addDescriptor(psd);
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(Event event) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT);
psd.visited = true;
psd.statement.setInt(1, event.getType().getId());
psd.statement.setInt(2, event.getEventProducer().getId());
psd.statement.setLong(3, event.getTimestamp());
psd.statement.setInt(4, event.getCpu());
psd.statement.setInt(5, event.getPage());
psd.statement.setInt(6, event.getCategory());
psd.statement.setLong(7, event.getLongPar());
psd.statement.setDouble(8, event.getDoublePar());
psd.statement.setInt(9, event.getId());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(EventType eventType) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_TYPE);
psd.visited = true;
psd.statement.setInt(1, eventType.getCategory());
psd.statement.setString(2, eventType.getName());
psd.statement.setInt(3, eventType.getId());
psd.statement.addBatch();
traceDB.getEventTypeCache().put(eventType);
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(EventParam eventParam) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_PARAM);
psd.visited = true;
psd.statement.setInt(1, eventParam.getEvent().getId());
psd.statement.setInt(2, eventParam.getEventParamType().getId());
psd.statement.setString(3, eventParam.getValue());
psd.statement.setInt(4, eventParam.getId());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
@Override
public void visit(EventParamType eventParamType) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_PARAM_TYPE);
psd.visited = true;
psd.statement.setInt(1, eventParamType.getEventType().getId());
psd.statement.setString(2, eventParamType.getName());
psd.statement.setString(3, eventParamType.getType());
psd.statement.setInt(4, eventParamType.getId());
psd.statement.addBatch();
traceDB.getEventTypeCache().put(eventParamType);
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* Event Producers
*/
@Override
public void visit(EventProducer eventProducer) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.EVENT_PRODUCER);
psd.visited = true;
psd.statement.setString(1, eventProducer.getType());
psd.statement.setString(2, eventProducer.getLocalId());
psd.statement.setString(3, eventProducer.getName());
psd.statement.setInt(4, eventProducer.getParentId());
psd.statement.setInt(5, eventProducer.getId());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* File
*/
@Override
public void visit(File file) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.FILE);
psd.visited = true;
psd.statement.setString(1, file.getPath());
psd.statement.setString(2, file.getDescription());
psd.statement.setInt(3, file.getId());
psd.statement.addBatch();
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* Results
*/
/**
* Note 1: the TYPE of an analysis result CANNOT be updated to avoid DB inconsistencies. E.g. :
* - search result saved - search result updated to group result in the AnalysisResult object -
* the update operation tries to update groups before not existing! The correct approach in this
* kind of situation is: - delete the old result - create a new result of a different type
*
* Note 2: processed trace results cannot be updated because not meaningful.
*
* Note 3: if your AnalysisResultData are not changed and only AnalysisResult metadata must be
* updated, just put data to null and they will be skipped.
*/
@Override
public void visit(AnalysisResult analysisResult) throws SoCTraceException {
try {
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.ANALYSIS_RESULT);
psd.visited = true;
psd.statement.setInt(1, analysisResult.getTool().getId());
// XXX see note at the bottom of ModelVisitor.java
psd.statement.setString(2, SoctraceUtils.timestampToString(analysisResult.getDate()));
psd.statement.setString(3, analysisResult.getDescription());
psd.statement.setInt(4, analysisResult.getId());
psd.statement.addBatch();
if (analysisResult.getData() == null)
return;
String type = analysisResult.getType();
if (type.equals(AnalysisResultType.TYPE_SEARCH.toString())) {
updateSearchResult(analysisResult);
} else if (type.equals(AnalysisResultType.TYPE_GROUP.toString())) {
updateGroupResult(analysisResult);
} else if (type.equals(AnalysisResultType.TYPE_ANNOTATION.toString())) {
updateAnnotationResult(analysisResult);
} else if (type.equals(AnalysisResultType.TYPE_PROCESSED_TRACE.toString())) {
; // nothing to do.
}
} catch (SQLException e) {
throw new SoCTraceException(e);
}
}
/*
* U t i l i t i e s
*/
/**
* TARGET_ENTITY cannot be updated to avoid inconsistencies in the DB.
*/
private void updateSearchResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultSearchData data = (AnalysisResultSearchData) analysisResult.getData();
// Note: only the SEARCH table may be updated
PreparedStatementDescriptor psd = getDescriptor(FramesocTable.SEARCH);
psd.visited = true;
psd.statement.setString(1, data.getSearchCommand());
psd.statement.setInt(2, analysisResult.getId());
psd.statement.addBatch();
}
private void updateGroupResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultGroupData data = (AnalysisResultGroupData) analysisResult.getData();
PreparedStatementDescriptor psdGroup = getDescriptor(FramesocTable.ENTITY_GROUP);
PreparedStatementDescriptor psdMapping = getDescriptor(FramesocTable.GROUP_MAPPING);
psdGroup.visited = true;
psdMapping.visited = true;
DepthFirstIterator treeIt = data.getDepthFirstIterator();
while (treeIt.hasNext()) {
Group g = treeIt.next();
psdGroup.statement.setInt(1, g.getParentId());
psdGroup.statement.setString(2, g.getName());
psdGroup.statement.setString(3, g.getTargetEntity());
psdGroup.statement.setString(4, g.getGroupingOperator());
psdGroup.statement.setBoolean(5, g.isOrdered());
psdGroup.statement.setInt(6, g.getSequenceNumber());
psdGroup.statement.setInt(7, analysisResult.getId());
psdGroup.statement.setInt(8, g.getId());
psdGroup.statement.addBatch();
// For leafs only the position currently updated.
// This is meaningful only for ordered groups.
if (g instanceof OrderedGroup) {
Map<Integer, LeafMapping> leaves = ((OrderedGroup) g).getSonLeaves();
Iterator<Entry<Integer, LeafMapping>> it = leaves.entrySet().iterator();
while (it.hasNext()) {
Entry<Integer, LeafMapping> entry = (Entry<Integer, LeafMapping>) it.next();
psdMapping.statement.setInt(1, entry.getKey());
psdMapping.statement.setInt(2, analysisResult.getId());
psdMapping.statement.setInt(3, entry.getValue().getMappingId());
psdMapping.statement.addBatch();
}
}
}
}
private void updateAnnotationResult(AnalysisResult analysisResult) throws SQLException,
SoCTraceException {
AnalysisResultAnnotationData annotationData = (AnalysisResultAnnotationData) analysisResult
.getData();
PreparedStatementDescriptor psdAnnotation = getDescriptor(FramesocTable.ANNOTATION);
PreparedStatementDescriptor psdAnnotationType = getDescriptor(FramesocTable.ANNOTATION_TYPE);
PreparedStatementDescriptor psdAnnotationParam = getDescriptor(FramesocTable.ANNOTATION_PARAM);
PreparedStatementDescriptor psdAnnotationParamType = getDescriptor(FramesocTable.ANNOTATION_PARAM_TYPE);
psdAnnotation.visited = true;
psdAnnotationType.visited = true;
psdAnnotationParam.visited = true;
psdAnnotationParamType.visited = true;
for (AnnotationType at : annotationData.getAnnotationTypes()) {
psdAnnotationType.statement.setString(1, at.getName());
psdAnnotationType.statement.setInt(2, analysisResult.getId());
psdAnnotationType.statement.setInt(3, at.getId());
psdAnnotationType.statement.addBatch();
for (AnnotationParamType pt : at.getParamTypes()) {
psdAnnotationParamType.statement.setInt(1, pt.getAnnotationType().getId());
psdAnnotationParamType.statement.setString(2, pt.getName());
psdAnnotationParamType.statement.setString(3, pt.getType());
psdAnnotationParamType.statement.setInt(4, analysisResult.getId());
psdAnnotationParamType.statement.setInt(5, pt.getId());
psdAnnotationParamType.statement.addBatch();
}
}
for (Annotation a : annotationData.getAnnotations()) {
psdAnnotation.statement.setInt(1, a.getAnnotationType().getId());
psdAnnotation.statement.setString(2, a.getName());
psdAnnotation.statement.setInt(3, analysisResult.getId());
psdAnnotation.statement.setInt(4, a.getId());
psdAnnotation.statement.addBatch();
for (AnnotationParam p : a.getParams()) {
psdAnnotationParam.statement.setInt(1, a.getId());
psdAnnotationParam.statement.setInt(2, p.getAnnotationParamType().getId());
psdAnnotationParam.statement.setString(3, p.getValue());
psdAnnotationParam.statement.setInt(4, analysisResult.getId());
psdAnnotationParam.statement.setInt(5, p.getId());
psdAnnotationParam.statement.addBatch();
}
}
}
}