/******************************************************************************* * 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.query.distribution; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.inria.soctrace.lib.model.EventType; import fr.inria.soctrace.lib.model.utils.SoCTraceException; import fr.inria.soctrace.lib.query.ValueListString; import fr.inria.soctrace.lib.storage.TraceDBObject; import fr.inria.soctrace.lib.utils.DeltaManager; /** * Implementation of the {@link HEventIterator} interface, * reading events block by block. * * The block size is predefined. * * @author "Generoso Pagano <generoso.pagano@inria.fr>" */ class HEventIdBlockIteratorImpl implements HEventIterator { /** * Logger */ private final static Logger logger = LoggerFactory.getLogger(HEventIdBlockIteratorImpl.class); private TraceDBObject traceDB; private Iterator<HEvent> eIterator; private List<HEvent> eList; private String typeIds; private int numOfTypes; private long startTimestamp = Long.MIN_VALUE; private long endTimestamp = Long.MIN_VALUE; private boolean hasNext = true; private int nextId = Integer.MIN_VALUE; private final static int MAXSIZE = 1000000; public boolean hasNext() { return hasNext; } public HEvent getNext() throws SoCTraceException { if (eIterator==null || !eIterator.hasNext()) { if (!hasNext) { clear(); return null; } eIterator = null; if (eList!=null) { eList.clear(); eList = null; } eList = getBlock(traceDB); eIterator = eList.iterator(); } if (eIterator.hasNext()) // in the case an empty list has been loaded return eIterator.next(); return null; } private List<HEvent> getBlock(TraceDBObject traceDB) throws SoCTraceException { List<HEvent> list = new LinkedList<HEvent>(); try { DeltaManager dm = new DeltaManager(); dm.start(); // prepare query int numberOfTraceTypes = traceDB.getEventTypeCache().getElementMap(EventType.class).values().size(); boolean typecond = (numOfTypes < numberOfTraceTypes); boolean timecond = (startTimestamp!=Long.MIN_VALUE || endTimestamp!=Long.MIN_VALUE); StringBuilder sb = new StringBuilder("SELECT ID, TIMESTAMP FROM EVENT WHERE ID >= " + nextId); if (typecond) { sb.append(" AND EVENT_TYPE_ID IN " + typeIds); } if (timecond) { sb.append(" AND TIMESTAMP BETWEEN " + startTimestamp + " AND " + endTimestamp); } sb.append(" ORDER BY ID " ); sb.append(" LIMIT " + MAXSIZE); logger.debug(sb.toString()); Statement stm = traceDB.getConnection().createStatement(); ResultSet rs = stm.executeQuery(sb.toString()); int count = 0; while (rs.next()) { HEvent he = new HEvent(); nextId = rs.getInt(1); he.timestamp = rs.getLong(2); list.add(he); count++; } if (count==0) hasNext = false; nextId++; stm.close(); logger.debug(dm.endMessage("Next id: " + (nextId))); } catch (SQLException e) { throw new SoCTraceException(e); } return list; } @Override public void setTraceDB(TraceDBObject traceDB) throws SoCTraceException { this.traceDB = traceDB; } @Override public void setTypes(List<EventType> types) throws SoCTraceException { ValueListString vls = new ValueListString(); Set<Integer> tset = new HashSet<Integer>(); numOfTypes = 0; for (EventType et: types) { if (tset.contains(et.getId())) continue; vls.addValue(String.valueOf(et.getId())); tset.add(et.getId()); numOfTypes++; } this.typeIds = vls.getValueString(); } @Override public void setTimestamps(long startTimestamp, long endTimestamp) { this.startTimestamp = startTimestamp; this.endTimestamp = endTimestamp; } @Override public void clear() { hasNext = true; startTimestamp = Long.MIN_VALUE; endTimestamp = Long.MIN_VALUE; nextId = Integer.MIN_VALUE; typeIds = ""; numOfTypes = 0; traceDB = null; eIterator = null; if (eList!=null) { eList.clear(); eList = null; } } }