/******************************************************************************* * 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; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import fr.inria.soctrace.lib.model.EventParamType; import fr.inria.soctrace.lib.model.EventType; import fr.inria.soctrace.lib.model.utils.ModelConstants.EventCategory; import fr.inria.soctrace.lib.model.utils.SoCTraceException; import fr.inria.soctrace.lib.storage.utils.ModelElementCache; import fr.inria.soctrace.lib.storage.utils.SQLConstants.FramesocTable; import fr.inria.soctrace.lib.storage.visitors.TraceDBDeleteVisitor; import fr.inria.soctrace.lib.storage.visitors.TraceDBSaveVisitor; import fr.inria.soctrace.lib.storage.visitors.TraceDBUpdateVisitor; /** * Object used to deal with a SoC-Trace Trace DB. * * @author "Generoso Pagano <generoso.pagano@inria.fr>" */ public class TraceDBObject extends DBObject { /** * Element format (type and param types) cache */ private ModelElementCache eventTypeCache = null; /** * The constructor. */ public TraceDBObject(String name, DBMode mode) throws SoCTraceException { super(name, mode); } /** * Static builder. Create a new TraceDBObject instance * opening the (existing) database. * * @return a new trace db object * @throws SoCTraceException */ public static TraceDBObject openNewInstance(String dbName) throws SoCTraceException { return new TraceDBObject(dbName, DBMode.DB_OPEN); } @Override protected void createDB() throws SoCTraceException { if (dbManager.isDBExisting()) throw new SoCTraceException("Database "+dbManager.getDBName()+" already present"); // create the DB and the tables dbManager.createDB(); dbManager.createTableStatement(); dbManager.initEvent(); dbManager.initEventType(); dbManager.initEventParam(); dbManager.initEventParamType(); dbManager.initEventProducer(); dbManager.initFile(); dbManager.initAnalysisResult(); dbManager.initAnnotation(); dbManager.initAnnotationType(); dbManager.initAnnotationParam(); dbManager.initAnnotationParamType(); dbManager.initGroup(); dbManager.initGroupMapping(); dbManager.initSearch(); dbManager.initSearchMapping(); dbManager.initProcessedTrace(); dbManager.closeTableStatement(); // commit commit(); } @Override protected void openDB() throws SoCTraceException { dbManager.openConnection(); } @Override protected void cleanCache() { if (eventTypeCache != null) eventTypeCache.clear(); eventTypeCache = null; } /** * Structure cache getter. * The cache is lazy initialized. * * @return the structure cache * @throws SoCTraceException */ public ModelElementCache getEventTypeCache() throws SoCTraceException { if (eventTypeCache == null) loadEventStructureCache(); return eventTypeCache; } /** * Load the event structure from the DB. * The DB should so contain a valid structure. */ private synchronized void loadEventStructureCache() throws SoCTraceException { // double check in synchronized environment if (eventTypeCache != null) return; eventTypeCache = new ModelElementCache(); eventTypeCache.addElementMap(EventType.class); eventTypeCache.addElementMap(EventParamType.class); Statement stm; ResultSet rs; try { stm = dbManager.getConnection().createStatement(); // load EventType rs = stm.executeQuery("SELECT * FROM " + FramesocTable.EVENT_TYPE); while (rs.next()) { EventType et = new EventType(rs.getInt("ID"), rs.getInt("CATEGORY")); et.setName(rs.getString("NAME")); eventTypeCache.put(et); } // load EventTypeParam rs = stm.executeQuery("SELECT * FROM " + FramesocTable.EVENT_PARAM_TYPE); while (rs.next()) { EventParamType ept = new EventParamType(rs.getInt("ID")); ept.setName(rs.getString("NAME")); ept.setType(rs.getString("TYPE")); ept.setEventType(eventTypeCache.get(EventType.class, rs.getInt("EVENT_TYPE_ID"))); eventTypeCache.put(ept); } stm.close(); } catch (SQLException e) { throw new SoCTraceException(e); } } @Override protected void initializeVisitors() throws SoCTraceException { saveVisitor = new TraceDBSaveVisitor(this); deleteVisitor = new TraceDBDeleteVisitor(this); updateVisitor = new TraceDBUpdateVisitor(this); } /** * Get the number of type entity in the trace. * * @param entityType * the type of entity that must be retireved * @return the number of type entity in the trace * @throws SoCTraceException */ public int getNumberOf(FramesocTable entityType) throws SoCTraceException { Statement stm; ResultSet rs; int value = 0; try { stm = dbManager.getConnection().createStatement(); rs = stm.executeQuery("SELECT COUNT(*) FROM " + entityType); while (rs.next()) { value = rs.getInt(1); } stm.close(); return value; } catch (SQLException e) { throw new SoCTraceException(e); } } public long getMinPage() throws SoCTraceException { return getValue("MIN", "PAGE", FramesocTable.EVENT); } public long getMaxPage() throws SoCTraceException { return getValue("MAX", "PAGE", FramesocTable.EVENT); } public long getMinTimestamp() throws SoCTraceException { return getValue("MIN", "TIMESTAMP", FramesocTable.EVENT); } public long getMaxTimestamp() throws SoCTraceException { /* * Single query implementation of this request: * * select max(REALMAX) from * (select * case * when TIMESTAMP>=LPAR then TIMESTAMP * else LPAR * end * as REALMAX * from EVENT where CATEGORY IN (1,2)); */ long maxTs = getValue("MAX", "TIMESTAMP", FramesocTable.EVENT); long maxEndTs = getMaxEndTimestamp(); return Math.max(maxTs, maxEndTs); } /** * Create an index on the timestamp column of EVENT table. * * @throws SoCTraceException */ public void createTimestampIndex() throws SoCTraceException { dbManager.createIndex(FramesocTable.EVENT.toString(), "TIMESTAMP", "ts_index"); } /** * Create an index on the event id column of EVENT_PARAM table. * * @throws SoCTraceException */ public void createEventParamIndex() throws SoCTraceException { dbManager.createIndex(FramesocTable.EVENT_PARAM.toString(), "EVENT_ID", "ep_index"); } /** * Drop the index on the timestamp column of EVENT table. * * @throws SoCTraceException */ public void dropTimestampIndex() throws SoCTraceException { dbManager.dropIndex(FramesocTable.EVENT.toString(), "ts_index"); } /** * Drop the index on the event id column of EVENT_PARAM table. * * @throws SoCTraceException */ public void dropEventParamIndex() throws SoCTraceException { dbManager.dropIndex(FramesocTable.EVENT_PARAM.toString(), "ep_index"); } private long getValue(String operation, String column, FramesocTable table) throws SoCTraceException { Statement stm; ResultSet rs; long value = 0; try { stm = dbManager.getConnection().createStatement(); rs = stm.executeQuery("SELECT "+operation+"("+column+") FROM " + table); while (rs.next()) { value = rs.getLong(1); } stm.close(); return value; } catch (SQLException e) { throw new SoCTraceException(e); } } private long getMaxEndTimestamp() throws SoCTraceException { Statement stm; ResultSet rs; long value = 0; try { stm = dbManager.getConnection().createStatement(); rs = stm.executeQuery("SELECT MAX(LPAR) FROM EVENT " + "WHERE CATEGORY IN ("+EventCategory.LINK+", "+EventCategory.STATE+")"); while (rs.next()) { value = rs.getLong(1); } stm.close(); return value; } catch (SQLException e) { throw new SoCTraceException(e); } } }