Merge master in TmfTraceModel
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / events / TmfEventsCache.java
CommitLineData
2d55fd20
FC
1/*******************************************************************************\r
2 * Copyright (c) 2011 Ericsson\r
ce2388e0 3 *\r
2d55fd20
FC
4 * All rights reserved. This program and the accompanying materials are\r
5 * made available under the terms of the Eclipse Public License v1.0 which\r
6 * accompanies this distribution, and is available at\r
7 * http://www.eclipse.org/legal/epl-v10.html\r
ce2388e0 8 *\r
2d55fd20
FC
9 * Contributors:\r
10 * Patrick Tasse - Initial API and implementation\r
11 ******************************************************************************/\r
12\r
13package org.eclipse.linuxtools.tmf.ui.viewers.events;\r
14\r
15import java.util.ArrayList;\r
16\r
17import org.eclipse.core.runtime.IProgressMonitor;\r
18import org.eclipse.core.runtime.IStatus;\r
19import org.eclipse.core.runtime.Status;\r
20import org.eclipse.core.runtime.jobs.Job;\r
6c13869b 21import org.eclipse.linuxtools.tmf.core.component.ITmfDataProvider;\r
ce2388e0 22import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;\r
6c13869b
FC
23import org.eclipse.linuxtools.tmf.core.filter.ITmfFilter;\r
24import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;\r
25import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
2d55fd20
FC
26\r
27public class TmfEventsCache {\r
28\r
5a5c2fc7 29 public static class CachedEvent {\r
ce2388e0 30 ITmfEvent event;\r
2d55fd20
FC
31 long rank;\r
32\r
ce2388e0
FC
33 public CachedEvent (ITmfEvent iTmfEvent, long rank) {\r
34 this.event = iTmfEvent;\r
2d55fd20
FC
35 this.rank = rank;\r
36 }\r
37 }\r
38\r
ce2388e0 39 private final CachedEvent[] fCache;\r
2d55fd20
FC
40 private int fCacheStartIndex = 0;\r
41 private int fCacheEndIndex = 0;\r
42\r
5d3e8747 43 private ITmfTrace<?> fTrace;\r
ce2388e0 44 private final TmfEventsTable fTable;\r
2d55fd20 45 private ITmfFilter fFilter;\r
ce2388e0 46 private final ArrayList<Integer> fFilterIndex = new ArrayList<Integer>(); // contains the event rank at each 'cache size' filtered events\r
2d55fd20
FC
47\r
48 public TmfEventsCache(int cacheSize, TmfEventsTable table) {\r
49 fCache = new CachedEvent[cacheSize];\r
50 fTable = table;\r
51 }\r
ce2388e0 52\r
5d3e8747 53 public void setTrace(ITmfTrace<?> trace) {\r
2d55fd20
FC
54 fTrace = trace;\r
55 clear();\r
56 }\r
ce2388e0 57\r
5a5c2fc7 58 public synchronized void clear() {\r
2d55fd20
FC
59 fCacheStartIndex = 0;\r
60 fCacheEndIndex = 0;\r
61 fFilterIndex.clear();\r
62 }\r
63\r
64 public void applyFilter(ITmfFilter filter) {\r
65 fFilter = filter;\r
66 clear();\r
67 }\r
ce2388e0 68\r
2d55fd20
FC
69 public void clearFilter() {\r
70 fFilter = null;\r
71 clear();\r
72 }\r
ce2388e0 73\r
5a5c2fc7 74 public synchronized CachedEvent getEvent(int index) {\r
2d55fd20
FC
75 if ((index >= fCacheStartIndex) && (index < fCacheEndIndex)) {\r
76 int i = index - fCacheStartIndex;\r
77 return fCache[i];\r
78 }\r
79 populateCache(index);\r
80 return null;\r
81 }\r
82\r
5a5c2fc7 83 public synchronized CachedEvent peekEvent(int index) {\r
2d55fd20
FC
84 if ((index >= fCacheStartIndex) && (index < fCacheEndIndex)) {\r
85 int i = index - fCacheStartIndex;\r
86 return fCache[i];\r
87 }\r
88 return null;\r
89 }\r
ce2388e0
FC
90\r
91 public synchronized void storeEvent(ITmfEvent event, long rank, int index) {\r
2d55fd20
FC
92 if (fCacheStartIndex == fCacheEndIndex) {\r
93 fCacheStartIndex = index;\r
94 fCacheEndIndex = index;\r
95 }\r
96 if (index == fCacheEndIndex) {\r
97 int i = index - fCacheStartIndex;\r
98 if (i < fCache.length) {\r
99 fCache[i] = new CachedEvent(event.clone(), rank);\r
100 fCacheEndIndex++;\r
101 }\r
102 }\r
ce2388e0 103 if ((fFilter != null) && ((index % fCache.length) == 0)) {\r
2d55fd20 104 int i = index / fCache.length;\r
5a5c2fc7 105 fFilterIndex.add(i, Integer.valueOf((int) rank));\r
2d55fd20
FC
106 }\r
107 }\r
ce2388e0 108\r
2d55fd20 109 @SuppressWarnings("unchecked")\r
5a5c2fc7 110 public synchronized int getFilteredEventIndex(final long rank) {\r
2d55fd20
FC
111 int current;\r
112 int startRank;\r
ce2388e0 113 TmfDataRequest<ITmfEvent> request;\r
2d55fd20
FC
114 synchronized (this) {\r
115 int start = 0;\r
116 int end = fFilterIndex.size();\r
ce2388e0
FC
117\r
118 if ((fCacheEndIndex - fCacheStartIndex) > 1) {\r
2d55fd20 119 if (rank < fCache[0].rank) {\r
ce2388e0 120 end = (fCacheStartIndex / fCache.length) + 1;\r
2d55fd20
FC
121 } else if (rank > fCache[fCacheEndIndex - fCacheStartIndex - 1].rank) {\r
122 start = fCacheEndIndex / fCache.length;\r
123 } else {\r
ce2388e0 124 for (int i = 0; i < (fCacheEndIndex - fCacheStartIndex); i++) {\r
2d55fd20
FC
125 if (fCache[i].rank >= rank) {\r
126 return fCacheStartIndex + i;\r
127 }\r
128 }\r
129 return fCacheEndIndex;\r
130 }\r
131 }\r
ce2388e0 132\r
2d55fd20
FC
133 current = (start + end) / 2;\r
134 while (current != start) {\r
135 if (rank < fFilterIndex.get(current)) {\r
136 end = current;\r
137 current = (start + end) / 2;\r
138 } else {\r
139 start = current;\r
140 current = (start + end) / 2;\r
141 }\r
142 }\r
143 startRank = fFilterIndex.get(current);\r
144 }\r
ce2388e0 145\r
2d55fd20 146 final int index = current * fCache.length;\r
ce2388e0
FC
147\r
148 class DataRequest<T extends ITmfEvent> extends TmfDataRequest<T> {\r
2d55fd20
FC
149 int fRank;\r
150 int fIndex;\r
ce2388e0 151\r
2d55fd20
FC
152 DataRequest(Class<T> dataType, int start, int nbRequested) {\r
153 super(dataType, start, nbRequested);\r
154 fRank = start;\r
155 fIndex = index;\r
156 }\r
ce2388e0 157\r
2d55fd20
FC
158 @Override\r
159 public void handleData(T event) {\r
160 super.handleData(event);\r
ce2388e0
FC
161 if (isCancelled()) {\r
162 return;\r
163 }\r
2d55fd20
FC
164 if (fRank >= rank) {\r
165 cancel();\r
166 return;\r
167 }\r
168 fRank++;\r
169 if (fFilter.matches(event)) {\r
170 fIndex++;\r
171 }\r
172 }\r
173\r
174 public int getFilteredIndex() {\r
175 return fIndex;\r
176 }\r
177 }\r
ce2388e0
FC
178\r
179 request = new DataRequest<ITmfEvent>(ITmfEvent.class, startRank, TmfDataRequest.ALL_DATA);\r
180 ((ITmfDataProvider<ITmfEvent>) fTrace).sendRequest(request);\r
2d55fd20
FC
181 try {\r
182 request.waitForCompletion();\r
ce2388e0 183 return ((DataRequest<ITmfEvent>) request).getFilteredIndex();\r
2d55fd20
FC
184 } catch (InterruptedException e) {\r
185 }\r
186 return 0;\r
187 }\r
ce2388e0 188\r
2d55fd20
FC
189 // ------------------------------------------------------------------------\r
190 // Event cache population\r
191 // ------------------------------------------------------------------------\r
ce2388e0 192\r
2d55fd20
FC
193 // The event fetching job\r
194 private Job job;\r
195 private synchronized void populateCache(final int index) {\r
196\r
197 /* Check if the current job will fetch the requested event:\r
198 * 1. The job must exist\r
199 * 2. It must be running (i.e. not completed)\r
200 * 3. The requested index must be within the cache range\r
ce2388e0 201 *\r
2d55fd20
FC
202 * If the job meets these conditions, we simply exit.\r
203 * Otherwise, we create a new job but we might have to cancel\r
204 * an existing job for an obsolete range.\r
205 */\r
206 if (job != null) {\r
207 if (job.getState() != Job.NONE) {\r
ce2388e0 208 if ((index >= fCacheStartIndex) && (index < (fCacheStartIndex + fCache.length))) {\r
2d55fd20
FC
209 return;\r
210 }\r
211 // The new index is out of the requested range\r
212 // Kill the job and start a new one\r
213 job.cancel();\r
214 }\r
215 }\r
ce2388e0 216\r
2d55fd20
FC
217 fCacheStartIndex = index;\r
218 fCacheEndIndex = index;\r
219\r
220 job = new Job("Fetching Events") { //$NON-NLS-1$\r
221 private int startIndex = index;\r
222 private int skipCount = 0;\r
223 @Override\r
224 @SuppressWarnings("unchecked")\r
225 protected IStatus run(final IProgressMonitor monitor) {\r
226\r
227 int nbRequested;\r
228 if (fFilter == null) {\r
229 nbRequested = fCache.length;\r
230 } else {\r
231 nbRequested = TmfDataRequest.ALL_DATA;\r
232 int i = index / fCache.length;\r
233 if (i < fFilterIndex.size()) {\r
234 startIndex = fFilterIndex.get(i);\r
235 skipCount = index - (i * fCache.length);\r
236 }\r
237 }\r
ce2388e0
FC
238\r
239 TmfDataRequest<ITmfEvent> request = new TmfDataRequest<ITmfEvent>(ITmfEvent.class, startIndex, nbRequested) {\r
2d55fd20
FC
240 private int count = 0;\r
241 private long rank = startIndex;\r
242 @Override\r
ce2388e0 243 public void handleData(ITmfEvent event) {\r
2d55fd20
FC
244 // If the job is canceled, cancel the request so waitForCompletion() will unlock\r
245 if (monitor.isCanceled()) {\r
246 cancel();\r
247 return;\r
248 }\r
249 super.handleData(event);\r
250 if (event != null) {\r
ce2388e0 251 if (((fFilter == null) || fFilter.matches(event)) && (skipCount-- <= 0)) {\r
2d55fd20
FC
252 synchronized (TmfEventsCache.this) {\r
253 fCache[count] = new CachedEvent(event.clone(), rank);\r
254 count++;\r
255 fCacheEndIndex++;\r
256 }\r
257 if (fFilter != null) {\r
258 fTable.cacheUpdated(false);\r
259 }\r
260 }\r
261 }\r
262 if (count >= fCache.length) {\r
263 cancel();\r
ce2388e0 264 } else if ((fFilter != null) && (count >= (fTable.getTable().getItemCount() - 3))) { // -1 for header row, -2 for top and bottom filter status rows\r
2d55fd20
FC
265 cancel();\r
266 }\r
267 rank++;\r
268 }\r
269 };\r
270\r
ce2388e0 271 ((ITmfDataProvider<ITmfEvent>) fTrace).sendRequest(request);\r
2d55fd20
FC
272 try {\r
273 request.waitForCompletion();\r
274 } catch (InterruptedException e) {\r
275 e.printStackTrace();\r
276 }\r
277\r
278 fTable.cacheUpdated(true);\r
ce2388e0 279\r
2d55fd20
FC
280 // Flag the UI thread that the cache is ready\r
281 if (monitor.isCanceled()) {\r
282 return Status.CANCEL_STATUS;\r
283 } else {\r
284 return Status.OK_STATUS;\r
285 }\r
286 }\r
287 };\r
288 //job.setSystem(true);\r
289 job.setPriority(Job.SHORT);\r
290 job.schedule();\r
291 }\r
292\r
293}\r
This page took 0.040084 seconds and 5 git commands to generate.