blob: 7e4be177ce52a0e81f19b42fc36f4ab9dc44048a [file] [log] [blame]
HIGUCHI Yuta9092db82016-01-03 18:45:01 -08001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.events;
17
18import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
19import static org.onlab.util.Tools.groupedThreads;
20import static org.onlab.util.Tools.minPriority;
21
22import java.util.Deque;
23import java.util.concurrent.ConcurrentLinkedDeque;
24import java.util.concurrent.ScheduledExecutorService;
25import java.util.concurrent.TimeUnit;
26
27import org.apache.felix.scr.annotations.Activate;
28import org.apache.felix.scr.annotations.Component;
29import org.apache.felix.scr.annotations.Deactivate;
30import org.apache.felix.scr.annotations.Property;
31import org.apache.felix.scr.annotations.Reference;
32import org.apache.felix.scr.annotations.ReferenceCardinality;
33import org.apache.felix.scr.annotations.Service;
34import org.onlab.util.UnmodifiableDeque;
35import org.onosproject.cluster.ClusterEvent;
36import org.onosproject.cluster.ClusterEventListener;
37import org.onosproject.cluster.ClusterService;
38import org.onosproject.core.ApplicationId;
39import org.onosproject.core.CoreService;
40import org.onosproject.event.Event;
41import org.onosproject.event.ListenerTracker;
42import org.onosproject.mastership.MastershipEvent;
43import org.onosproject.mastership.MastershipListener;
44import org.onosproject.mastership.MastershipService;
45import org.onosproject.net.device.DeviceEvent;
46import org.onosproject.net.device.DeviceListener;
47import org.onosproject.net.device.DeviceService;
48import org.onosproject.net.host.HostEvent;
49import org.onosproject.net.host.HostListener;
50import org.onosproject.net.host.HostService;
51import org.onosproject.net.link.LinkEvent;
52import org.onosproject.net.link.LinkListener;
53import org.onosproject.net.link.LinkService;
54import org.onosproject.net.topology.TopologyEvent;
55import org.onosproject.net.topology.TopologyListener;
56import org.onosproject.net.topology.TopologyService;
57import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60/**
61 * Application to store history of instance local ONOS Events.
62 */
63@Component(immediate = true)
64@Service
65public class EventHistoryManager
66 implements EventHistoryService {
67
68 private final Logger log = LoggerFactory.getLogger(getClass());
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected CoreService coreService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected MastershipService mastershipService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected DeviceService deviceService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected LinkService linkService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected TopologyService topologyService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected HostService hostService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected ClusterService clusterService;
90
91 @Property(name = "excludeStatsEvent", boolValue = true,
92 label = "Exclude stats related events")
93 private boolean excludeStatsEvent = true;
94
95 @Property(name = "sizeLimit", intValue = 10_000,
96 label = "Number of event history to store")
97 private int sizeLimit = 10_000;
98
99 private ApplicationId appId;
100
101 private ListenerTracker listeners;
102
103 // Using Deque so that it'll be possible to iterate from both ends
104 // (Tail-end is the most recent event)
105 private final Deque<Event<?, ?>> history = new ConcurrentLinkedDeque<>();
106
107 private ScheduledExecutorService pruner;
108
109 // pruneEventHistoryTask() execution interval in seconds
110 private long pruneInterval = 5;
111
112
113 @Activate
114 protected void activate() {
115 appId = coreService.registerApplication("org.onosproject.events");
116 log.debug("Registered as {}", appId);
117
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800118 pruner = newSingleThreadScheduledExecutor(
119 minPriority(groupedThreads("onos/events", "history-pruner", log)));
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800120
121 pruner.scheduleWithFixedDelay(this::pruneEventHistoryTask,
Jian Li68c4fc42016-01-11 16:07:03 -0800122 pruneInterval, pruneInterval, TimeUnit.SECONDS);
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800123
124 listeners = new ListenerTracker();
125 listeners.addListener(mastershipService, new InternalMastershipListener())
126 .addListener(deviceService, new InternalDeviceListener())
127 .addListener(linkService, new InternalLinkListener())
128 .addListener(topologyService, new InternalTopologyListener())
129 .addListener(hostService, new InternalHostListener())
130 .addListener(clusterService, new InternalClusterListener());
131
132 log.info("Started");
133 }
134
135 @Deactivate
136 protected void deactivate() {
137 listeners.removeListeners();
138
139 pruner.shutdownNow();
140 history.clear();
141
142 log.info("Stopped");
143 }
144
145 @Override
146 public Deque<Event<?, ?>> history() {
147 return UnmodifiableDeque.unmodifiableDeque(history);
148 }
149
150 @Override
151 public void clear() {
152 history.clear();
153 }
154
155 // This method assumes only 1 call is in flight at the same time.
156 private void pruneEventHistoryTask() {
157 int size = history.size();
158 int overflows = size - sizeLimit;
159 if (overflows > 0) {
160 for (int i = 0; i < overflows; ++i) {
161 history.poll();
162 }
163 }
164 }
165
166 private void addEvent(Event<?, ?> event) {
167 history.offer(event);
168 }
169
170 class InternalMastershipListener
171 implements MastershipListener {
172
173 @Override
174 public void event(MastershipEvent event) {
175 addEvent(event);
176 }
177 }
178
179 class InternalDeviceListener
180 implements DeviceListener {
181
182 @Override
183 public boolean isRelevant(DeviceEvent event) {
184 if (excludeStatsEvent) {
185 return event.type() != DeviceEvent.Type.PORT_STATS_UPDATED;
186 } else {
187 return true;
188 }
189 }
190
191 @Override
192 public void event(DeviceEvent event) {
193 addEvent(event);
194 }
195 }
196
197 class InternalLinkListener
198 implements LinkListener {
199
200 @Override
201 public void event(LinkEvent event) {
202 addEvent(event);
203 }
204 }
205
206 class InternalTopologyListener
207 implements TopologyListener {
208
209 @Override
210 public void event(TopologyEvent event) {
211 addEvent(event);
212 }
213 }
214
215 class InternalHostListener
216 implements HostListener {
217
218 @Override
219 public void event(HostEvent event) {
220 addEvent(event);
221 }
222 }
223
224 class InternalClusterListener
225 implements ClusterEventListener {
226
227 @Override
228 public void event(ClusterEvent event) {
229 addEvent(event);
230 }
231 }
232
233}