| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2014, 2015 Ericsson |
| 3 | * |
| 4 | * All rights reserved. This program and the accompanying materials are |
| 5 | * made available under the terms of the Eclipse Public License v1.0 which |
| 6 | * accompanies this distribution, and is available at |
| 7 | * http://www.eclipse.org/legal/epl-v10.html |
| 8 | * |
| 9 | * Contributors: |
| 10 | * Alexandre Montplaisir - Initial API and implementation |
| 11 | * Matthew Khouzam - Add the task state system from figure 3 from the spec |
| 12 | *******************************************************************************/ |
| 13 | |
| 14 | package org.eclipse.tracecompass.btf.core.analysis; |
| 15 | |
| 16 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
| 17 | |
| 18 | import org.eclipse.tracecompass.btf.core.event.BtfEvent; |
| 19 | import org.eclipse.tracecompass.btf.core.trace.BtfColumnNames; |
| 20 | import org.eclipse.tracecompass.btf.core.trace.BtfTrace; |
| 21 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; |
| 22 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; |
| 23 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; |
| 24 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; |
| 25 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; |
| 26 | import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider; |
| 27 | import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider; |
| 28 | |
| 29 | /** |
| 30 | * State provider for the default BTF analysis. |
| 31 | * |
| 32 | * The generated attribute tree will look like this: |
| 33 | * |
| 34 | * <pre> |
| 35 | * {root} |
| 36 | * +- Cores |
| 37 | * | +- Core 1 (not running/Name of the running Task) |
| 38 | * | +- Core 2 (not running/Name of the running Task) |
| 39 | * | |
| 40 | * +- Tasks |
| 41 | * +- Task A |
| 42 | * | +- Core 1 (not running/running/suspended) |
| 43 | * | | +- Runnable A1 (not running/running/suspended) |
| 44 | * | | +- Runnable A2 (not running/running/suspended) |
| 45 | * | +- Core 2 |
| 46 | * | | +- Runnable A1 |
| 47 | * | | +- Runnable A2 |
| 48 | * | +- ActiveCore |
| 49 | * | |
| 50 | * +- Task B |
| 51 | * +- Core 1 |
| 52 | * | +- Runnable B1 |
| 53 | * | +- Runnable B2 |
| 54 | * +- Core 2 |
| 55 | * | +- Runnable B1 |
| 56 | * | +- Runnable B2 |
| 57 | * +- ActiveCore |
| 58 | * </pre> |
| 59 | * |
| 60 | * @author Alexandre Montplaisir |
| 61 | */ |
| 62 | public class BtfStateProvider extends AbstractTmfStateProvider { |
| 63 | |
| 64 | private static final int PROVIDER_VERSION = 3; |
| 65 | |
| 66 | private static class TmfNamedStateValue { |
| 67 | private final String fName; |
| 68 | private final TmfStateValue fValue; |
| 69 | |
| 70 | public TmfNamedStateValue(TmfStateValue value, String name) { |
| 71 | fValue = value; |
| 72 | fName = name; |
| 73 | } |
| 74 | |
| 75 | public TmfStateValue getValue() { |
| 76 | return fValue; |
| 77 | } |
| 78 | |
| 79 | @Override |
| 80 | public String toString() { |
| 81 | return fName; |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | private static final TmfNamedStateValue STATE_CORE_IDLE = new TmfNamedStateValue(TmfStateValue.newValueInt(0), "Idle"); //$NON-NLS-1$ |
| 86 | |
| 87 | private static final TmfNamedStateValue STATE_NOT_RUNNING = new TmfNamedStateValue(TmfStateValue.nullValue(), "Not Running"); //$NON-NLS-1$ |
| 88 | private static final TmfNamedStateValue STATE_RUNNING = new TmfNamedStateValue(TmfStateValue.newValueInt((1)), "RUNNING"); //$NON-NLS-1$ |
| 89 | private static final TmfNamedStateValue STATE_SUSPENDED = new TmfNamedStateValue(TmfStateValue.newValueInt((2)), "SUSPENDED"); //$NON-NLS-1$ |
| 90 | |
| 91 | private static final TmfNamedStateValue STATE_TASK_ACTIVE = new TmfNamedStateValue(TmfStateValue.newValueInt((4)), "Active"); //$NON-NLS-1$ |
| 92 | private static final TmfNamedStateValue STATE_TASK_READY = new TmfNamedStateValue(TmfStateValue.newValueInt((5)), "Ready"); //$NON-NLS-1$ |
| 93 | private static final TmfNamedStateValue STATE_TASK_RUNNING = new TmfNamedStateValue(TmfStateValue.newValueInt((6)), "Task Running"); //$NON-NLS-1$ |
| 94 | private static final TmfNamedStateValue STATE_TASK_WAITING = new TmfNamedStateValue(TmfStateValue.newValueInt((7)), "Waiting"); //$NON-NLS-1$ |
| 95 | private static final TmfNamedStateValue STATE_TASK_PARKING = new TmfNamedStateValue(TmfStateValue.newValueInt((8)), "Parking"); //$NON-NLS-1$ |
| 96 | private static final TmfNamedStateValue STATE_TASK_POLLING = new TmfNamedStateValue(TmfStateValue.newValueInt((9)), "Polling"); //$NON-NLS-1$ |
| 97 | private static final TmfNamedStateValue STATE_TASK_TERMINATED = new TmfNamedStateValue(TmfStateValue.nullValue(), "Terminated"); //$NON-NLS-1$ |
| 98 | |
| 99 | private static final String ENTITY_CORE = "Core"; //$NON-NLS-1$ |
| 100 | private static final String ENTITY_TASK = "TASK"; //$NON-NLS-1$ |
| 101 | // private static final String ENTITY_RUNNABLE = "RUNNABLE"; |
| 102 | |
| 103 | private static final String ATTRIBUTE_TASKS = "Tasks"; //$NON-NLS-1$ |
| 104 | private static final String ATTRIBUTE_CORES = "Cores"; //$NON-NLS-1$ |
| 105 | private static final String ATTRIBUTE_ACTIVE_CORE = "ActiveCore"; //$NON-NLS-1$ |
| 106 | |
| 107 | /** |
| 108 | * Constructor |
| 109 | * |
| 110 | * @param trace |
| 111 | * The trace for which we will be building this state system |
| 112 | */ |
| 113 | public BtfStateProvider(BtfTrace trace) { |
| 114 | super(trace, "Btf State Provider"); //$NON-NLS-1$ |
| 115 | } |
| 116 | |
| 117 | @Override |
| 118 | public BtfTrace getTrace() { |
| 119 | return (BtfTrace) super.getTrace(); |
| 120 | } |
| 121 | |
| 122 | @Override |
| 123 | public int getVersion() { |
| 124 | return PROVIDER_VERSION; |
| 125 | } |
| 126 | |
| 127 | @Override |
| 128 | public ITmfStateProvider getNewInstance() { |
| 129 | return new BtfStateProvider(getTrace()); |
| 130 | } |
| 131 | |
| 132 | @Override |
| 133 | protected void eventHandle(ITmfEvent ev) { |
| 134 | if (!(ev instanceof BtfEvent)) { |
| 135 | return; |
| 136 | } |
| 137 | |
| 138 | BtfEvent event = (BtfEvent) ev; |
| 139 | final ITmfStateSystemBuilder ssb = checkNotNull(getStateSystemBuilder()); |
| 140 | |
| 141 | final long ts = event.getTimestamp().getValue(); |
| 142 | final String eventType = (String) event.getContent().getField(BtfColumnNames.EVENT.toString()).getValue(); |
| 143 | final String source = event.getSource(); |
| 144 | final String target = event.getTarget(); |
| 145 | String task; |
| 146 | int quark; |
| 147 | try { |
| 148 | switch (eventType) { |
| 149 | |
| 150 | case "activate": //$NON-NLS-1$ |
| 151 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_ACTIVE); |
| 152 | break; |
| 153 | |
| 154 | case "start": //$NON-NLS-1$ |
| 155 | case "resume": //$NON-NLS-1$ |
| 156 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_RUNNING); |
| 157 | |
| 158 | if (source.startsWith(ENTITY_CORE)) { |
| 159 | String core = source; |
| 160 | task = target; |
| 161 | |
| 162 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, core); |
| 163 | ssb.modifyAttribute(ts, STATE_RUNNING.getValue(), quark); |
| 164 | |
| 165 | /* Mark this task as active in the ActiveCore attribute */ |
| 166 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, ATTRIBUTE_ACTIVE_CORE); |
| 167 | ITmfStateValue value = TmfStateValue.newValueString(core); |
| 168 | ssb.modifyAttribute(ts, value, quark); |
| 169 | |
| 170 | /* Mark this task as active in the Cores/* attribute */ |
| 171 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_CORES, core); |
| 172 | /* Until the view can display the string */ |
| 173 | value = STATE_RUNNING.getValue(); |
| 174 | ssb.modifyAttribute(ts, value, quark); |
| 175 | |
| 176 | } else if (source.startsWith(ENTITY_TASK)) { |
| 177 | task = source; |
| 178 | String runnable = target; |
| 179 | String core = getCoreOfTask(ssb, task); |
| 180 | |
| 181 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, core, runnable); |
| 182 | ssb.modifyAttribute(ts, STATE_RUNNING.getValue(), quark); |
| 183 | } |
| 184 | break; |
| 185 | |
| 186 | case "suspend": //$NON-NLS-1$ |
| 187 | /* "suspend" events only happen on Tasks */ |
| 188 | if (source.startsWith(ENTITY_TASK)) { |
| 189 | task = source; |
| 190 | String runnable = target; |
| 191 | String core = getCoreOfTask(ssb, task); |
| 192 | |
| 193 | /* We'll update both the Core and Runnable attributes */ |
| 194 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, core); |
| 195 | ssb.modifyAttribute(ts, STATE_SUSPENDED.getValue(), quark); |
| 196 | quark = ssb.getQuarkRelativeAndAdd(quark, runnable); |
| 197 | ssb.modifyAttribute(ts, STATE_SUSPENDED.getValue(), quark); |
| 198 | } |
| 199 | break; |
| 200 | |
| 201 | case "terminate": //$NON-NLS-1$ |
| 202 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_TERMINATED); |
| 203 | |
| 204 | if (source.startsWith(ENTITY_CORE)) { |
| 205 | String core = source; |
| 206 | task = target; |
| 207 | |
| 208 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, core); |
| 209 | ssb.modifyAttribute(ts, STATE_NOT_RUNNING.getValue(), quark); |
| 210 | |
| 211 | /* Remove our "active task on core" bookmark */ |
| 212 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, ATTRIBUTE_ACTIVE_CORE); |
| 213 | ITmfStateValue value = TmfStateValue.nullValue(); |
| 214 | ssb.modifyAttribute(ts, value, quark); |
| 215 | |
| 216 | /* Mark the Cores/* attribute as not running */ |
| 217 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_CORES, core); |
| 218 | ssb.modifyAttribute(ts, STATE_CORE_IDLE.getValue(), quark); |
| 219 | |
| 220 | } else if (source.startsWith(ENTITY_TASK)) { |
| 221 | task = source; |
| 222 | String runnable = target; |
| 223 | String core = getCoreOfTask(ssb, task); |
| 224 | |
| 225 | quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task, core, runnable); |
| 226 | ssb.modifyAttribute(ts, STATE_NOT_RUNNING.getValue(), quark); |
| 227 | } |
| 228 | break; |
| 229 | |
| 230 | case "preempt": //$NON-NLS-1$ |
| 231 | case "release": //$NON-NLS-1$ |
| 232 | case "release_parking": //$NON-NLS-1$ |
| 233 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_READY); |
| 234 | break; |
| 235 | case "wait": //$NON-NLS-1$ |
| 236 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_WAITING); |
| 237 | break; |
| 238 | case "park": //$NON-NLS-1$ |
| 239 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_PARKING); |
| 240 | break; |
| 241 | case "poll": //$NON-NLS-1$ |
| 242 | //$FALL-THROUGH$ |
| 243 | case "poll_parking": //$NON-NLS-1$ |
| 244 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_POLLING); |
| 245 | break; |
| 246 | case "run": //$NON-NLS-1$ |
| 247 | updateTaskStateSystem(ssb, ts, event, STATE_TASK_RUNNING); |
| 248 | break; |
| 249 | default: |
| 250 | break; |
| 251 | |
| 252 | } |
| 253 | } catch (AttributeNotFoundException e) { |
| 254 | throw new IllegalStateException(e); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | private static void updateTaskStateSystem( |
| 259 | final ITmfStateSystemBuilder ssb, |
| 260 | final long ts, BtfEvent event, |
| 261 | TmfNamedStateValue stateValue) |
| 262 | throws AttributeNotFoundException { |
| 263 | String name = event.getType().getName(); |
| 264 | if (name.equals("Task")) { //$NON-NLS-1$ |
| 265 | String task = event.getTarget(); |
| 266 | int quark = ssb.getQuarkAbsoluteAndAdd(ATTRIBUTE_TASKS, task); |
| 267 | ssb.modifyAttribute(ts, stateValue.getValue(), quark); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | private static String getCoreOfTask(ITmfStateSystemBuilder ssb, String task) { |
| 272 | try { |
| 273 | int quark = ssb.getQuarkAbsolute(ATTRIBUTE_TASKS, task, ATTRIBUTE_ACTIVE_CORE); |
| 274 | ITmfStateValue value = ssb.queryOngoingState(quark); |
| 275 | return value.unboxStr(); |
| 276 | } catch (AttributeNotFoundException e) { |
| 277 | throw new IllegalStateException(e); |
| 278 | } |
| 279 | } |
| 280 | } |