blob: 3a07fff7c235934e994634f9dcaa67add5b40345 [file] [log] [blame]
HIGUCHI Yuta9092db82016-01-03 18:45:01 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
HIGUCHI Yuta9092db82016-01-03 18:45:01 -08003 *
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;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080035import org.onosproject.cluster.ClusterService;
36import org.onosproject.core.ApplicationId;
37import org.onosproject.core.CoreService;
38import org.onosproject.event.Event;
39import org.onosproject.event.ListenerTracker;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080040import org.onosproject.mastership.MastershipService;
41import org.onosproject.net.device.DeviceEvent;
42import org.onosproject.net.device.DeviceListener;
43import org.onosproject.net.device.DeviceService;
Yuta HIGUCHI4e3af862016-07-21 16:03:34 -070044import org.onosproject.net.edge.EdgePortService;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080045import org.onosproject.net.host.HostService;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080046import org.onosproject.net.link.LinkService;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080047import org.onosproject.net.topology.TopologyService;
48import org.slf4j.Logger;
49import org.slf4j.LoggerFactory;
50
51/**
52 * Application to store history of instance local ONOS Events.
53 */
54@Component(immediate = true)
55@Service
56public class EventHistoryManager
57 implements EventHistoryService {
58
59 private final Logger log = LoggerFactory.getLogger(getClass());
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected CoreService coreService;
63
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 protected MastershipService mastershipService;
66
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected DeviceService deviceService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected LinkService linkService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected TopologyService topologyService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected HostService hostService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected ClusterService clusterService;
81
Yuta HIGUCHI4e3af862016-07-21 16:03:34 -070082 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected EdgePortService edgeService;
84
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080085 @Property(name = "excludeStatsEvent", boolValue = true,
86 label = "Exclude stats related events")
87 private boolean excludeStatsEvent = true;
88
89 @Property(name = "sizeLimit", intValue = 10_000,
90 label = "Number of event history to store")
91 private int sizeLimit = 10_000;
92
93 private ApplicationId appId;
94
95 private ListenerTracker listeners;
96
97 // Using Deque so that it'll be possible to iterate from both ends
98 // (Tail-end is the most recent event)
99 private final Deque<Event<?, ?>> history = new ConcurrentLinkedDeque<>();
100
101 private ScheduledExecutorService pruner;
102
103 // pruneEventHistoryTask() execution interval in seconds
104 private long pruneInterval = 5;
105
106
107 @Activate
108 protected void activate() {
109 appId = coreService.registerApplication("org.onosproject.events");
110 log.debug("Registered as {}", appId);
111
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800112 pruner = newSingleThreadScheduledExecutor(
113 minPriority(groupedThreads("onos/events", "history-pruner", log)));
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800114
115 pruner.scheduleWithFixedDelay(this::pruneEventHistoryTask,
Jian Li68c4fc42016-01-11 16:07:03 -0800116 pruneInterval, pruneInterval, TimeUnit.SECONDS);
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800117
118 listeners = new ListenerTracker();
Yuta HIGUCHId90dbc92016-08-04 18:35:21 -0700119 listeners.addListener(mastershipService, this::addEvent)
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800120 .addListener(deviceService, new InternalDeviceListener())
Yuta HIGUCHId90dbc92016-08-04 18:35:21 -0700121 .addListener(linkService, this::addEvent)
122 .addListener(topologyService, this::addEvent)
123 .addListener(hostService, this::addEvent)
124 .addListener(clusterService, this::addEvent)
Yuta HIGUCHI4e3af862016-07-21 16:03:34 -0700125 .addListener(edgeService, this::addEvent);
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800126
127 log.info("Started");
128 }
129
130 @Deactivate
131 protected void deactivate() {
132 listeners.removeListeners();
133
134 pruner.shutdownNow();
135 history.clear();
136
137 log.info("Stopped");
138 }
139
140 @Override
141 public Deque<Event<?, ?>> history() {
142 return UnmodifiableDeque.unmodifiableDeque(history);
143 }
144
145 @Override
146 public void clear() {
147 history.clear();
148 }
149
150 // This method assumes only 1 call is in flight at the same time.
151 private void pruneEventHistoryTask() {
152 int size = history.size();
153 int overflows = size - sizeLimit;
154 if (overflows > 0) {
155 for (int i = 0; i < overflows; ++i) {
156 history.poll();
157 }
158 }
159 }
160
161 private void addEvent(Event<?, ?> event) {
162 history.offer(event);
163 }
164
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800165 class InternalDeviceListener
166 implements DeviceListener {
167
168 @Override
169 public boolean isRelevant(DeviceEvent event) {
170 if (excludeStatsEvent) {
171 return event.type() != DeviceEvent.Type.PORT_STATS_UPDATED;
172 } else {
173 return true;
174 }
175 }
176
177 @Override
178 public void event(DeviceEvent event) {
179 addEvent(event);
180 }
181 }
182
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800183}