segStore: guard size() in segment stores
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.segmentstore.core / src / org / eclipse / tracecompass / internal / segmentstore / core / arraylist / ArrayListStore.java
CommitLineData
3dde9149
MK
1/*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
664a3a81 10package org.eclipse.tracecompass.internal.segmentstore.core.arraylist;
3dde9149
MK
11
12import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.Collections;
17import java.util.Comparator;
18import java.util.Iterator;
19import java.util.List;
20import java.util.concurrent.locks.ReadWriteLock;
21import java.util.concurrent.locks.ReentrantReadWriteLock;
22import java.util.stream.Collectors;
23
24import org.eclipse.jdt.annotation.NonNull;
25import org.eclipse.jdt.annotation.Nullable;
2047fe04 26import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
3dde9149
MK
27import org.eclipse.tracecompass.segmentstore.core.ISegment;
28import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
664a3a81 29import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
3dde9149
MK
30
31import com.google.common.collect.ImmutableList;
664a3a81 32import com.google.common.collect.Ordering;
3dde9149
MK
33
34/**
35 * Implementation of an {@link ISegmentStore} using one in-memory
36 * {@link ArrayList}. This relatively simple implementation holds everything in
37 * memory, and as such cannot contain too much data.
38 *
39 * The ArrayListStore itself is {@link Iterable}, and its iteration order will
40 * be by ascending order of start times. For segments with identical start
41 * times, the secondary comparator will be the end time. If even those are
42 * equal, it will defer to the segments' natural ordering (
43 * {@link ISegment#compareTo}).
44 *
45 * The store's tree maps will not accept duplicate key-value pairs, which means
46 * that if you want several segments with the same start and end times, make
47 * sure their compareTo() differentiates them.
48 *
49 * Removal operations are not supported.
50 *
51 * @param <E>
52 * The type of segment held in this store
53 *
54 * @author Matthew Khouzam
55 */
56public class ArrayListStore<@NonNull E extends ISegment> implements ISegmentStore<E> {
57
664a3a81
LPD
58 private final Comparator<E> COMPARATOR = Ordering.from(SegmentComparators.INTERVAL_START_COMPARATOR)
59 .compound(SegmentComparators.INTERVAL_END_COMPARATOR);
3dde9149
MK
60
61 private final ReadWriteLock fLock = new ReentrantReadWriteLock(false);
62
aa9082f9 63 private final List<E> fStore;
3dde9149
MK
64
65 private @Nullable transient Iterable<E> fLastSnapshot = null;
66
67 /**
68 * Constructor
69 */
70 public ArrayListStore() {
aa9082f9 71 fStore = new ArrayList<>();
3dde9149
MK
72 }
73
aa9082f9
MK
74 /**
75 * Constructor
76 *
77 * @param array
78 * an array of elements to wrap in the segment store
79 *
80 */
81 public ArrayListStore(Object[] array) {
82 fStore = new ArrayList<>();
83 for (int i = 0; i < array.length; i++) {
84 if (array[i] instanceof ISegment) {
85 fStore.add((E) array[i]);
86 }
87 }
88 fStore.sort(COMPARATOR);
89 }
3dde9149
MK
90 // ------------------------------------------------------------------------
91 // Methods from Collection
92 // ------------------------------------------------------------------------
93
94 @Override
95 public Iterator<E> iterator() {
96 fLock.readLock().lock();
97 try {
98 Iterable<E> lastSnapshot = fLastSnapshot;
99 if (lastSnapshot == null) {
100 lastSnapshot = ImmutableList.copyOf(fStore);
101 fLastSnapshot = lastSnapshot;
102 }
103 return checkNotNull(lastSnapshot.iterator());
104 } finally {
105 fLock.readLock().unlock();
106 }
107 }
108
109 @Override
110 public boolean add(@Nullable E val) {
111 if (val == null) {
112 throw new IllegalArgumentException("Cannot add null value"); //$NON-NLS-1$
113 }
114
115 fLock.writeLock().lock();
116 try {
2047fe04
LPD
117 int insertPoint = Collections.binarySearch(fStore, val);
118 insertPoint = insertPoint >= 0 ? insertPoint : -insertPoint - 1;
119 fStore.add(insertPoint, val);
581e0f63 120 fLastSnapshot = null;
3dde9149
MK
121 return true;
122 } finally {
123 fLock.writeLock().unlock();
124 }
125 }
126
127 @Override
128 public int size() {
524fb56d
MK
129 fLock.readLock().lock();
130 try {
131 return fStore.size();
132 } finally {
133 fLock.readLock().unlock();
134 }
3dde9149
MK
135 }
136
137 @Override
138 public boolean isEmpty() {
f601ac35
MK
139 fLock.readLock().lock();
140 try {
141 return fStore.isEmpty();
142 } finally {
143 fLock.readLock().unlock();
144 }
3dde9149
MK
145 }
146
147 @Override
148 public boolean contains(@Nullable Object o) {
149 fLock.readLock().lock();
150 try {
151 return fStore.contains(o);
152 } finally {
153 fLock.readLock().unlock();
154 }
155 }
156
157 @Override
158 public boolean containsAll(@Nullable Collection<?> c) {
159 fLock.readLock().lock();
160 try {
161 return fStore.containsAll(c);
162 } finally {
163 fLock.readLock().unlock();
164 }
165 }
166
167 @Override
168 public Object[] toArray() {
169 fLock.readLock().lock();
170 try {
171 return fStore.toArray();
172 } finally {
173 fLock.readLock().unlock();
174 }
175 }
176
177 @Override
178 public <T> T[] toArray(T[] a) {
179 fLock.readLock().lock();
180 try {
181 return fStore.toArray(a);
182 } finally {
183 fLock.readLock().unlock();
184 }
185 }
186
187 @Override
188 public boolean remove(@Nullable Object o) {
189 throw new UnsupportedOperationException();
190 }
191
192 @Override
193 public boolean addAll(@Nullable Collection<? extends E> c) {
194 if (c == null) {
195 throw new IllegalArgumentException();
196 }
197
198 fLock.writeLock().lock();
199 try {
200 boolean changed = false;
201 for (E elem : c) {
202 if (this.add(elem)) {
203 changed = true;
204 }
205 }
206 return changed;
207 } finally {
208 fLock.writeLock().unlock();
209 }
210 }
211
212 @Override
213 public boolean removeAll(@Nullable Collection<?> c) {
214 throw new UnsupportedOperationException();
215 }
216
217 @Override
218 public boolean retainAll(@Nullable Collection<?> c) {
219 throw new UnsupportedOperationException();
220 }
221
222 @Override
223 public void clear() {
224 fLock.writeLock().lock();
225 try {
226 fStore.clear();
227 } finally {
228 fLock.writeLock().unlock();
229 }
230 }
231
232 // ------------------------------------------------------------------------
233 // Methods added by ISegmentStore
234 // ------------------------------------------------------------------------
235
236 @Override
237 public Iterable<E> getIntersectingElements(long position) {
238 /*
239 * The intervals intersecting 't' are those whose 1) start time is
240 * *lower* than 't' AND 2) end time is *higher* than 't'.
241 */
242 fLock.readLock().lock();
243 try {
2047fe04
LPD
244 /*
245 * as fStore is sorted by start then end times, restrict sub array
246 * to elements whose start times <= t as stream.filter won't do it.
247 */
248 int index = Collections.binarySearch(fStore, new BasicSegment(position, Long.MAX_VALUE));
249 index = (index >= 0) ? index : -index - 1;
250 return fStore.subList(0, index).stream().filter(element -> position >= element.getStart() && position <= element.getEnd()).collect(Collectors.toList());
3dde9149
MK
251 } finally {
252 fLock.readLock().unlock();
253 }
254 }
255
256 @Override
257 public Iterable<E> getIntersectingElements(long start, long end) {
258 fLock.readLock().lock();
259 try {
2047fe04
LPD
260 int index = Collections.binarySearch(fStore, new BasicSegment(end, Long.MAX_VALUE));
261 index = (index >= 0) ? index : -index - 1;
262 return fStore.subList(0, index).stream().filter(element -> !(start > element.getEnd() || end < element.getStart())).collect(Collectors.toList());
3dde9149
MK
263 } finally {
264 fLock.readLock().unlock();
265 }
266 }
267
268 @Override
269 public void dispose() {
270 fLock.writeLock().lock();
271 try {
272 fStore.clear();
273 } finally {
274 fLock.writeLock().unlock();
275 }
276 }
277}
This page took 0.039709 seconds and 5 git commands to generate.