|
1 package jdk.jfr.consumer; |
|
2 |
|
3 import java.time.Instant; |
|
4 import java.util.ArrayList; |
|
5 import java.util.Arrays; |
|
6 import java.util.List; |
|
7 import java.util.function.Consumer; |
|
8 |
|
9 import jdk.jfr.EventType; |
|
10 import jdk.jfr.consumer.AbstractEventStream.EventDispatcher; |
|
11 import jdk.jfr.internal.LongMap; |
|
12 import jdk.jfr.internal.Utils; |
|
13 import jdk.jfr.internal.consumer.InternalEventFilter; |
|
14 |
|
15 final class StreamConfiguration { |
|
16 private static final Runnable[] NO_ACTIONS = new Runnable[0]; |
|
17 |
|
18 Consumer<?>[] errorActions = new Consumer<?>[0]; |
|
19 private Runnable[] flushActions = NO_ACTIONS; |
|
20 private Runnable[] closeActions = NO_ACTIONS; |
|
21 private EventDispatcher[] dispatchers = EventDispatcher.NO_DISPATCHERS; |
|
22 private InternalEventFilter eventFilter = InternalEventFilter.ACCEPT_ALL; |
|
23 LongMap<EventDispatcher[]> dispatcherLookup = new LongMap<>(); |
|
24 |
|
25 private boolean changedConfiguration = false; |
|
26 private boolean closed = false; |
|
27 private boolean reuse = true; |
|
28 private boolean ordered = true; |
|
29 private Instant startTime = null; |
|
30 private Instant endTime = null; |
|
31 private boolean started = false; |
|
32 private long startNanos = 0; |
|
33 private long endNanos = Long.MAX_VALUE; |
|
34 |
|
35 // Cache the last event type and dispatch. |
|
36 EventType cacheEventType; |
|
37 EventDispatcher[] cacheDispatchers; |
|
38 |
|
39 |
|
40 public StreamConfiguration(StreamConfiguration configuration) { |
|
41 this.flushActions = configuration.flushActions; |
|
42 this.closeActions = configuration.closeActions; |
|
43 this.errorActions = configuration.errorActions; |
|
44 this.dispatchers = configuration.dispatchers; |
|
45 this.eventFilter = configuration.eventFilter; |
|
46 this.closed = configuration.closed; |
|
47 this.reuse = configuration.reuse; |
|
48 this.ordered = configuration.ordered; |
|
49 this.startTime = configuration.startTime; |
|
50 this.endTime = configuration.endTime; |
|
51 this.started = configuration.started; |
|
52 this.startNanos = configuration.startNanos; |
|
53 this.endNanos = configuration.endNanos; |
|
54 this.dispatcherLookup = configuration.dispatcherLookup; |
|
55 } |
|
56 |
|
57 public StreamConfiguration() { |
|
58 } |
|
59 |
|
60 public StreamConfiguration remove(Object action) { |
|
61 flushActions = remove(flushActions, action); |
|
62 closeActions = remove(closeActions, action); |
|
63 errorActions = remove(errorActions, action); |
|
64 dispatchers = removeDispatch(dispatchers, action); |
|
65 return this; |
|
66 } |
|
67 |
|
68 public StreamConfiguration addDispatcher(EventDispatcher e) { |
|
69 dispatchers = add(dispatchers, e); |
|
70 eventFilter = buildFilter(dispatchers); |
|
71 dispatcherLookup = new LongMap<>(); |
|
72 return this; |
|
73 } |
|
74 |
|
75 public StreamConfiguration addFlushAction(Runnable action) { |
|
76 flushActions = add(flushActions, action); |
|
77 return this; |
|
78 } |
|
79 |
|
80 public StreamConfiguration addCloseAction(Runnable action) { |
|
81 closeActions = add(closeActions, action); |
|
82 return this; |
|
83 } |
|
84 |
|
85 public StreamConfiguration addErrorAction(Consumer<Throwable> action) { |
|
86 errorActions = add(errorActions, action); |
|
87 return this; |
|
88 } |
|
89 |
|
90 public StreamConfiguration setClosed(boolean closed) { |
|
91 this.closed = closed; |
|
92 changedConfiguration = true; |
|
93 return this; |
|
94 } |
|
95 |
|
96 public boolean isClosed() { |
|
97 return closed; |
|
98 } |
|
99 |
|
100 public Runnable[] getCloseActions() { |
|
101 return closeActions; |
|
102 } |
|
103 |
|
104 public Runnable[] getFlushActions() { |
|
105 return flushActions; |
|
106 } |
|
107 |
|
108 private EventDispatcher[] removeDispatch(EventDispatcher[] array, Object action) { |
|
109 List<EventDispatcher> list = new ArrayList<>(array.length); |
|
110 boolean modified = false; |
|
111 for (int i = 0; i < array.length; i++) { |
|
112 if (array[i].action != action) { |
|
113 list.add(array[i]); |
|
114 } else { |
|
115 modified = true; |
|
116 } |
|
117 } |
|
118 EventDispatcher[] result = list.toArray(new EventDispatcher[0]); |
|
119 if (modified) { |
|
120 eventFilter = buildFilter(result); |
|
121 dispatcherLookup = new LongMap<>(); |
|
122 changedConfiguration = true; |
|
123 } |
|
124 return result; |
|
125 } |
|
126 |
|
127 private <T> T[] remove(T[] array, Object action) { |
|
128 List<T> list = new ArrayList<>(array.length); |
|
129 for (int i = 0; i < array.length; i++) { |
|
130 if (array[i] != action) { |
|
131 list.add(array[i]); |
|
132 } else { |
|
133 changedConfiguration = true; |
|
134 } |
|
135 } |
|
136 return list.toArray(array); |
|
137 } |
|
138 |
|
139 private <T> T[] add(T[] array, T object) { |
|
140 List<T> list = new ArrayList<>(Arrays.asList(array)); |
|
141 list.add(object); |
|
142 changedConfiguration = true; |
|
143 return list.toArray(array); |
|
144 } |
|
145 |
|
146 private static InternalEventFilter buildFilter(EventDispatcher[] dispatchers) { |
|
147 InternalEventFilter ef = new InternalEventFilter(); |
|
148 for (EventDispatcher ed : dispatchers) { |
|
149 String name = ed.eventName; |
|
150 if (name == null) { |
|
151 return InternalEventFilter.ACCEPT_ALL; |
|
152 } |
|
153 ef.setThreshold(name, 0); |
|
154 } |
|
155 return ef; |
|
156 } |
|
157 |
|
158 public StreamConfiguration setReuse(boolean reuse) { |
|
159 this.reuse = reuse; |
|
160 changedConfiguration = true; |
|
161 return this; |
|
162 } |
|
163 |
|
164 public StreamConfiguration setOrdered(boolean ordered) { |
|
165 this.ordered = ordered; |
|
166 changedConfiguration = true; |
|
167 return this; |
|
168 } |
|
169 |
|
170 public StreamConfiguration setEndTime(Instant endTime) { |
|
171 this.endTime = endTime; |
|
172 this.endNanos = Utils.timeToNanos(endTime); |
|
173 changedConfiguration = true; |
|
174 return this; |
|
175 } |
|
176 |
|
177 public StreamConfiguration setStartTime(Instant startTime) { |
|
178 this.startTime = startTime; |
|
179 this.startNanos = Utils.timeToNanos(startTime); |
|
180 changedConfiguration = true; |
|
181 return this; |
|
182 } |
|
183 |
|
184 public Instant getStartTime() { |
|
185 return startTime; |
|
186 } |
|
187 |
|
188 public Object getEndTime() { |
|
189 return endTime; |
|
190 } |
|
191 |
|
192 public boolean isStarted() { |
|
193 return started; |
|
194 } |
|
195 |
|
196 public StreamConfiguration setStartNanos(long startNanos) { |
|
197 this.startNanos = startNanos; |
|
198 changedConfiguration = true; |
|
199 return this; |
|
200 } |
|
201 |
|
202 public void setStarted(boolean started) { |
|
203 this.started = started; |
|
204 changedConfiguration = true; |
|
205 } |
|
206 |
|
207 public boolean hasChanged() { |
|
208 return changedConfiguration; |
|
209 } |
|
210 |
|
211 public boolean getReuse() { |
|
212 return reuse; |
|
213 } |
|
214 |
|
215 public boolean getOrdered() { |
|
216 return ordered; |
|
217 } |
|
218 |
|
219 public InternalEventFilter getFiler() { |
|
220 return eventFilter; |
|
221 } |
|
222 |
|
223 public long getStartNanos() { |
|
224 return startNanos; |
|
225 } |
|
226 |
|
227 public long getEndNanos() { |
|
228 return endNanos; |
|
229 } |
|
230 |
|
231 public InternalEventFilter getFilter() { |
|
232 return eventFilter; |
|
233 } |
|
234 |
|
235 public void clearDispatchCache() { |
|
236 cacheDispatchers = null; |
|
237 cacheEventType = null; |
|
238 } |
|
239 |
|
240 public String toString() { |
|
241 StringBuilder sb = new StringBuilder(); |
|
242 for (Runnable flush : flushActions) { |
|
243 sb.append("Flush Action: ").append(flush).append("\n"); |
|
244 } |
|
245 for (Runnable close : closeActions) { |
|
246 sb.append("Close Action: " + close + "\n"); |
|
247 } |
|
248 for (Consumer<?> error : errorActions) { |
|
249 sb.append("Error Action: " + error + "\n"); |
|
250 } |
|
251 for (EventDispatcher dispatcher : dispatchers) { |
|
252 sb.append("Dispatch Action: " + dispatcher.eventName + "(" + dispatcher + ") \n"); |
|
253 } |
|
254 sb.append("Closed: ").append(closed).append("\n"); |
|
255 sb.append("Reuse: ").append(reuse).append("\n"); |
|
256 sb.append("Ordered: ").append(ordered).append("\n"); |
|
257 sb.append("Started: ").append(started).append("\n"); |
|
258 sb.append("Start Time: ").append(startTime).append("\n"); |
|
259 sb.append("Start Nanos: ").append(startNanos).append("\n"); |
|
260 sb.append("End Time: ").append(endTime).append("\n"); |
|
261 sb.append("End Nanos: ").append(endNanos).append("\n"); |
|
262 return sb.toString(); |
|
263 } |
|
264 |
|
265 EventDispatcher[] getDispatchers() { |
|
266 return dispatchers; |
|
267 } |
|
268 } |