1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Ericsson
4 * All rights reserved. This program and the accompanying materials are made
5 * 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
10 * Matthew Khouzam - Initial API and implementation
11 * Simon Delisle - Added a method to remove the iterator
12 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ctf
.core
;
15 import java
.util
.ArrayList
;
16 import java
.util
.HashMap
;
17 import java
.util
.Random
;
20 * Ctf Iterator Manager, allows mapping of iterators (a limited resource) to
21 * contexts (many many resources).
23 * @author Matthew Khouzam
27 public abstract class CtfIteratorManager
{
29 * A side note synchronized works on the whole object, Therefore add and
30 * remove will be thread safe.
34 * The map of traces to trace managers.
36 private static HashMap
<CtfTmfTrace
, CtfTraceManager
> map
= new HashMap
<>();
39 * Registers a trace to the iterator manager, the trace can now get
43 * the trace to register.
45 public static synchronized void addTrace(final CtfTmfTrace trace
) {
46 map
.put(trace
, new CtfTraceManager(trace
));
50 * Removes a trace to the iterator manager.
53 * the trace to register.
55 public static synchronized void removeTrace(final CtfTmfTrace trace
) {
56 CtfTraceManager mgr
= map
.remove(trace
);
63 * Get an iterator for a given trace and context.
69 * @return the iterator
72 public static synchronized CtfIterator
getIterator(final CtfTmfTrace trace
,
73 final CtfTmfContext ctx
) {
74 return map
.get(trace
).getIterator(ctx
);
78 * Remove an iterator for a given trace and context
86 public static synchronized void removeIterator(final CtfTmfTrace trace
, final CtfTmfContext ctx
) {
87 CtfTraceManager traceManager
= map
.get(trace
);
88 if (traceManager
!= null) {
89 traceManager
.removeIterator(ctx
);
97 * @author Matthew Khouzam
99 class CtfTraceManager
{
101 * Cache size. Under 1023 on linux32 systems. Number of file handles
104 private final static int MAX_SIZE
= 100;
106 * The map of the cache.
108 private final HashMap
<CtfTmfContext
, CtfIterator
> fMap
;
110 * An array pointing to the same cache. this allows fast "random" accesses.
112 private final ArrayList
<CtfTmfContext
> fRandomAccess
;
116 private final CtfTmfTrace fTrace
;
118 * Random number generator
120 private final Random fRnd
;
122 public CtfTraceManager(CtfTmfTrace trace
) {
123 fMap
= new HashMap
<>();
124 fRandomAccess
= new ArrayList
<>();
125 fRnd
= new Random(System
.nanoTime());
130 * This needs explaining: the iterator table is effectively a cache.
131 * Originally the contexts had a 1 to 1 structure with the file handles of a
132 * trace. This failed since there is a limit to how many file handles we can
133 * have opened simultaneously. Then a round-robin scheme was implemented,
134 * this lead up to a two competing contexts syncing up and using the same
135 * file handler, causing horrible slowdowns. Now a random replacement
136 * algorithm is selected. This is the same as used by arm processors, and it
137 * works quite well when many cores so this looks promising for very
138 * multi-threaded systems.
141 * the context to look up
142 * @return the iterator referring to the context
144 public CtfIterator
getIterator(final CtfTmfContext context
) {
146 * if the element is in the map, we don't need to do anything else.
148 CtfIterator retVal
= fMap
.get(context
);
149 if (retVal
== null) {
151 * Assign an iterator to a context, this means we will need to seek
154 if (fRandomAccess
.size() < MAX_SIZE
) {
156 * if we're not full yet, just add an element.
158 retVal
= fTrace
.createIterator();
159 addElement(context
, retVal
);
163 * if we're full, randomly replace an element
165 retVal
= replaceRandomElement(context
);
167 if (context
.getLocation() != null) {
168 final CtfLocationInfo location
= (CtfLocationInfo
) context
.getLocation().getLocationInfo();
169 retVal
.seek(location
);
175 public void removeIterator(CtfTmfContext context
) {
176 fMap
.remove(context
);
177 fRandomAccess
.remove(context
);
181 * Add a pair of context and element to the hashmap and the arraylist.
188 private void addElement(final CtfTmfContext context
,
189 final CtfIterator elem
) {
190 fMap
.put(context
, elem
);
191 fRandomAccess
.add(context
);
195 * Replace a random element
198 * the context to swap in
199 * @return the iterator of the removed elements.
201 private CtfIterator
replaceRandomElement(
202 final CtfTmfContext context
) {
204 * This needs some explanation too: We need to select a random victim
205 * and remove it. The order of the elements is not important, so instead
206 * of just calling arraylist.remove(element) which has an O(n)
207 * complexity, we pick an random number. The element is swapped out of
208 * the array and removed and replaced in the hashmap.
210 final int size
= fRandomAccess
.size();
211 final int pos
= fRnd
.nextInt(size
);
212 final CtfTmfContext victim
= fRandomAccess
.get(pos
);
213 fRandomAccess
.set(pos
, context
);
214 final CtfIterator elem
= fMap
.remove(victim
);
215 fMap
.put(context
, elem
);
220 for (CtfIterator iterator
: fMap
.values()) {
224 fRandomAccess
.clear();