| /******************************************************************************* |
| * Copyright (c) 2013, 2016 Ericsson |
| * |
| * All rights reserved. This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Jean-Christian Kouamé - Initial API and implementation |
| * Patrick Tasse - Updates to mipmap feature |
| *******************************************************************************/ |
| package org.eclipse.tracecompass.internal.tmf.core.statesystem.mipmap; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.tracecompass.internal.tmf.core.Activator; |
| import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; |
| import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; |
| import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; |
| import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; |
| import org.eclipse.tracecompass.statesystem.core.interval.TmfStateInterval; |
| import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; |
| import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; |
| |
| /** |
| * The mipmap feature base implementation. |
| * |
| * @author Jean-Christian Kouamé |
| * @author Patrick Tasse |
| * |
| */ |
| public abstract class TmfMipmapFeature implements ITmfMipmapFeature { |
| |
| /** The current state value */ |
| protected @NonNull ITmfStateValue currentValue = TmfStateValue.nullValue(); |
| /** The current start time for the state value */ |
| protected long currentStartTime; |
| /** The list of ongoing state intervals per mipmap level */ |
| protected List<List<ITmfStateInterval>> intervals = new ArrayList<>(); |
| /** The state system used to store the mipmap attributes */ |
| protected ITmfStateSystemBuilder ss; |
| |
| private int mipmapResolution; |
| private int mipmapQuark; |
| private List<Integer> levelQuarks = new ArrayList<>(); |
| |
| /** |
| * Constructor |
| * |
| * @param baseQuark |
| * The quark of the attribute we want to mipmap |
| * @param mipmapQuark |
| * The quark of the mipmap feature attribute |
| * @param mipmapResolution |
| * The resolution that will be used for the mipmap |
| * @param ss |
| * The state system in which to insert the state changes |
| */ |
| public TmfMipmapFeature(int baseQuark, int mipmapQuark, int mipmapResolution, ITmfStateSystemBuilder ss) { |
| this.mipmapQuark = mipmapQuark; |
| this.mipmapResolution = mipmapResolution; |
| this.ss = ss; |
| |
| /* store the base attribute quark at level 0 */ |
| this.levelQuarks.add(baseQuark); |
| |
| /* create the level 0 list */ |
| intervals.add(new ArrayList<ITmfStateInterval>(mipmapResolution)); |
| } |
| |
| @Override |
| public void updateMipmap(ITmfStateValue value, long ts) { |
| /* if the value did not change, ignore it */ |
| if (currentValue.equals(value)) { |
| return; |
| } |
| |
| /* if the ongoing state value is not null, create and store a state interval */ |
| if (!currentValue.isNull()) { |
| ITmfStateInterval interval = new TmfStateInterval(currentStartTime, ts, getLevelQuark(0), currentValue.unboxValue()); |
| intervals.get(0).add(interval); |
| } |
| |
| /* if the new value is not null, update the mipmap levels that are full */ |
| if (!value.isNull()) { |
| int level = 0; |
| while (intervals.get(level).size() == getMipmapResolution()) { |
| updateMipmapLevel(++level, ts); |
| } |
| } |
| |
| /* store the new value as the ongoing state value */ |
| currentValue = value; |
| currentStartTime = ts; |
| } |
| |
| @Override |
| public void updateAndCloseMipmap() { |
| if (!currentValue.isNull()) { |
| ITmfStateInterval interval = new TmfStateInterval(currentStartTime, currentStartTime, getLevelQuark(0), currentValue.unboxValue()); |
| intervals.get(0).add(interval); |
| } |
| for (int level = 1; level <= getNbLevels(); level++) { |
| updateMipmapLevel(level, currentStartTime); |
| } |
| } |
| |
| /** |
| * Compute and update the mipmap level attribute from the lower-level |
| * state interval list |
| * |
| * @param level |
| * The mipmap level to update |
| * @param endTime |
| * The end timestamp to use for the mipmap interval |
| */ |
| protected void updateMipmapLevel(int level, long endTime) { |
| try { |
| /* get the lower-level interval list */ |
| List<ITmfStateInterval> lowerIntervals = intervals.get(level - 1); |
| if (lowerIntervals.isEmpty()) { |
| return; |
| } |
| |
| /* get the start time from the first interval in the lower-level list */ |
| long startTime = lowerIntervals.get(0).getStartTime(); |
| |
| /* compute the mipmap value */ |
| ITmfStateValue value = computeMipmapValue(lowerIntervals, startTime, endTime); |
| |
| /* clear the lower-level list */ |
| lowerIntervals.clear(); |
| |
| /* get or create the current-level quark */ |
| int levelQuark = ss.getQuarkRelativeAndAdd(mipmapQuark, String.valueOf(level)); |
| if (!checkLevelExists(level)) { |
| addLevelQuark(levelQuark); |
| ss.updateOngoingState(TmfStateValue.newValueInt(level), mipmapQuark); |
| intervals.add(new ArrayList<ITmfStateInterval>(getMipmapResolution())); |
| } |
| |
| /* add new interval to current-level list */ |
| ITmfStateInterval interval = new TmfStateInterval(startTime, endTime, levelQuark, value.unboxValue()); |
| intervals.get(level).add(interval); |
| |
| /* update the current-level attribute */ |
| ss.modifyAttribute(startTime, value.unboxValue(), levelQuark); |
| } catch (StateValueTypeException e) { |
| Activator.logError("TmfMipmapFeature : Bad state value type", e); //$NON-NLS-1$ |
| } catch (TimeRangeException e) { |
| Activator.logError("TmfMipmapFeature : Time stamp is out of range", e); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Compute the mipmap value from a list of lower-level state intervals |
| * |
| * @param lowerIntervals |
| * The list of lower-level state intervals |
| * @param startTime |
| * The start time of the mipmap interval |
| * @param endTime |
| * The end time of the mipmap interval |
| * @return A state value to be stored in the mipmap level attribute |
| */ |
| protected abstract @NonNull ITmfStateValue computeMipmapValue(List<ITmfStateInterval> lowerIntervals, long startTime, long endTime); |
| |
| /** |
| * Get the mipmap resolution |
| * |
| * @return The mipmap resolution for this feature |
| */ |
| protected int getMipmapResolution() { |
| return mipmapResolution; |
| } |
| |
| /** |
| * Get the mipmap feature quark. The state value |
| * of this attribute is the mipmap number of levels. |
| * This is the parent attribute of the mipmap level quarks. |
| * |
| * @return The attribute quark for this mipmap feature |
| */ |
| protected int getMipmapQuark() { |
| return mipmapQuark; |
| } |
| |
| /** |
| * Get the mipmap quark for the specified level. |
| * For level 0 the base attribute quark is returned. |
| * |
| * @param level |
| * The mipmap level (0 for the base attribute) |
| * @return The attribute quark for this mipmap level |
| */ |
| protected int getLevelQuark(int level) { |
| return levelQuarks.get(level); |
| } |
| |
| /** |
| * Add a new mipmap level quark. |
| * |
| * @param quark |
| * The attribute quark for the new mipmap level |
| */ |
| protected void addLevelQuark(int quark) { |
| levelQuarks.add(quark); |
| } |
| |
| /** |
| * Get the mipmap number of levels. |
| * |
| * @return The current number of mipmap levels for this feature |
| * (excluding the base attribute) |
| */ |
| protected int getNbLevels() { |
| return levelQuarks.size() - 1; |
| } |
| |
| /** |
| * Checks if a mipmap level exists. |
| * |
| * @param level |
| * The mipmap level to check |
| * @return true if this level exists, false otherwise |
| */ |
| protected boolean checkLevelExists(int level) { |
| return !(level >= levelQuarks.size() || level < 0); |
| } |
| |
| } |