1 /*******************************************************************************
2 * Copyright (c) 2014 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 * Alexandre Montplaisir - Renamed/extracted from CtfTraceManager
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.internal
.tmf
.ctf
.core
.trace
.iterator
;
15 import java
.util
.ArrayList
;
16 import java
.util
.HashMap
;
17 import java
.util
.List
;
19 import java
.util
.Random
;
20 import java
.util
.concurrent
.locks
.Lock
;
21 import java
.util
.concurrent
.locks
.ReentrantLock
;
23 import org
.eclipse
.tracecompass
.internal
.tmf
.ctf
.core
.Activator
;
24 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.context
.CtfLocationInfo
;
25 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.context
.CtfTmfContext
;
26 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.trace
.CtfTmfTrace
;
29 * A CTF trace iterator manager.
31 * Each instance of {@link CtfTmfTrace} should possess one of these, which will
32 * manage the iterators that are opened to read that trace. This will allow
33 * controlling the number of opened file handles per trace.
35 * @author Matthew Khouzam
37 public class CtfIteratorManager
{
39 * Cache size. Under 1023 on linux32 systems. Number of file handles
42 private static final int MAX_SIZE
= 100;
44 /** The map of the cache */
45 private final Map
<CtfTmfContext
, CtfIterator
> fMap
;
47 /** An array pointing to the same cache. this allows fast "random" accesses */
48 private final List
<CtfTmfContext
> fRandomAccess
;
50 /** Lock for when we access the two previous data structures */
51 private final Lock fAccessLock
= new ReentrantLock();
53 /** The parent trace */
54 private final CtfTmfTrace fTrace
;
56 /** Random number generator */
57 private final Random fRnd
;
63 * The trace whose iterators this manager will manage
65 public CtfIteratorManager(CtfTmfTrace trace
) {
66 fMap
= new HashMap
<>();
67 fRandomAccess
= new ArrayList
<>();
68 fRnd
= new Random(System
.nanoTime());
73 * This needs explaining: the iterator table is effectively a cache.
74 * Originally the contexts had a 1 to 1 structure with the file handles of a
75 * trace. This failed since there is a limit to how many file handles we can
76 * have opened simultaneously. Then a round-robin scheme was implemented,
77 * this lead up to a two competing contexts syncing up and using the same
78 * file handler, causing horrible slowdowns. Now a random replacement
79 * algorithm is selected. This is the same as used by arm processors, and it
80 * works quite well when many cores so this looks promising for very
81 * multi-threaded systems.
84 * the context to look up
85 * @return the iterator referring to the context
87 public CtfIterator
getIterator(final CtfTmfContext context
) {
89 * if the element is in the map, we don't need to do anything else.
91 CtfIterator iter
= fMap
.get(context
);
97 * Assign an iterator to a context.
99 if (fRandomAccess
.size() < MAX_SIZE
) {
101 * if we're not full yet, just add an element.
103 iter
= (CtfIterator
) fTrace
.createIterator();
104 addElement(context
, iter
);
108 * if we're full, randomly replace an element
110 iter
= replaceRandomElement(context
);
112 if (context
.getLocation() != null) {
113 final CtfLocationInfo location
= (CtfLocationInfo
) context
.getLocation().getLocationInfo();
117 fAccessLock
.unlock();
124 * Remove an iterator from this manager
127 * The context of the iterator to remove
129 public void removeIterator(CtfTmfContext context
) {
132 /* The try below is only to auto-call CtfIterator.close() */
133 try (CtfIterator removed
= fMap
.remove(context
)) {
136 fRandomAccess
.remove(context
);
139 fAccessLock
.unlock();
144 * Add a pair of context and element to the hashmap and the arraylist.
151 private void addElement(final CtfTmfContext context
,
152 final CtfIterator elem
) {
155 fMap
.put(context
, elem
);
156 fRandomAccess
.add(context
);
159 fAccessLock
.unlock();
164 * Replace a random element
167 * the context to swap in
168 * @return the iterator of the removed elements.
170 private CtfIterator
replaceRandomElement(final CtfTmfContext context
) {
172 * This needs some explanation too: We need to select a random victim
173 * and remove it. The order of the elements is not important, so instead
174 * of just calling arraylist.remove(element) which has an O(n)
175 * complexity, we pick an random number. The element is swapped out of
176 * the array and removed and replaced in the hashmap.
178 fAccessLock
.lock(); // just in case, should only be called when already locked
180 final int size
= fRandomAccess
.size();
181 final int pos
= fRnd
.nextInt(size
);
182 final CtfTmfContext victim
= fRandomAccess
.get(pos
);
183 fRandomAccess
.set(pos
, context
);
184 CtfIterator elem
= fMap
.remove(victim
);
185 if (elem
.isClosed()) {
187 * In case the iterator streams have been closed, we need to
188 * replace it by a fresh new one to access the trace. We also
189 * report that as an error as it should not happen.
191 Activator
.getDefault().logError("Found closed iterator in iterator manager for trace " + victim
.getTrace()); //$NON-NLS-1$
194 elem
= (CtfIterator
) fTrace
.createIterator();
196 fMap
.put(context
, elem
);
201 fAccessLock
.unlock();
206 * Dispose this iterator manager, which will close all the remaining
209 public void dispose() {
212 for (CtfIterator iterator
: fMap
.values()) {
216 fRandomAccess
.clear();
219 fAccessLock
.unlock();
This page took 0.036382 seconds and 5 git commands to generate.