blob: 69031ba9effe1121d3303373af94fd829a2c26ed [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
2 *
3 */
4package net.floodlightcontroller.util;
5
6import java.util.ArrayList;
7
8/**
9 * @author subrata
10 *
11 */
12
13public class EventHistory<T> {
14 public static final int EV_HISTORY_DEFAULT_SIZE = 1024;
15
16 public String description;
17 public int event_history_size;
18 public int current_index;
19 public boolean full; // true if all are in use
20 public ArrayList<Event> events;
21
22 public String getDescription() {
23 return description;
24 }
25 public int getEvent_history_size() {
26 return event_history_size;
27 }
28 public int getCurrent_index() {
29 return current_index;
30 }
31 public boolean isFull() {
32 return full;
33 }
34 public ArrayList<Event> getEvents() {
35 return events;
36 }
37
38 public class Event {
39 public EventHistoryBaseInfo base_info;
40 public T info;
41 }
42
43 public enum EvState {
44 FREE, // no valid event written yet
45 BEING_MODIFIED, // event is being updated with new value, skip
46 ACTIVE, // event is active and can be displayed
47 }
48
49 public enum EvAction {
50 ADDED, // specific entry added
51 REMOVED, // specific entry removed
52 UPDATED, // Entry updated
53 BLOCKED, // Blocked - used for Attachment Points
54 UNBLOCKED,
55 CLEARED, // All entries are removed
56 PKT_IN,
57 PKT_OUT,
58 SWITCH_CONNECTED,
59 SWITCH_DISCONNECTED,
60 LINK_ADDED,
61 LINK_DELETED,
62 LINK_PORT_STATE_UPDATED,
63 CLUSTER_ID_CHANGED_FOR_CLUSTER,
64 CLUSTER_ID_CHANGED_FOR_A_SWITCH,
65 }
66
67 // Constructor
68 public EventHistory(int maxEvents, String desc) {
69 events = new ArrayList<Event>(maxEvents);
70
71 for (int idx = 0; idx < maxEvents; idx++) {
72 Event evH = new Event();
73 evH.base_info = new EventHistoryBaseInfo();
74 evH.info = null;
75 evH.base_info.state = EvState.FREE;
76 evH.base_info.idx = idx;
77 events.add(idx, evH);
78 }
79
80 description = "Event-History:" + desc;
81 event_history_size = maxEvents;
82 current_index = 0;
83 full = false;
84 }
85
86 // Constructor for default size
87 public EventHistory(String desc) {
88 this(EV_HISTORY_DEFAULT_SIZE, desc);
89 }
90
91 // Copy constructor - copy latest k items of the event history
92 public EventHistory(EventHistory<T> eventHist, int latestK) {
93
94 if (eventHist == null) {
95 description = "No event found";
96 return;
97 }
98 int curSize = (eventHist.full)?eventHist.event_history_size:
99 eventHist.current_index;
100 int size = (latestK < curSize)?latestK:curSize;
101 int evIdx = eventHist.current_index;
102 int topSz = (evIdx >= size)?size:evIdx;
103
104 // Need to create a new one since size is different
105 events = new ArrayList<Event>(size);
106
107 // Get the top part
108 int origIdx = evIdx;
109 for (int idx = 0; idx < topSz; idx++) {
110 Event evH = eventHist.events.get(--origIdx);
111 evH.base_info.idx = idx;
112 events.add(idx, evH);
113 }
114
115 // Get the bottom part
116 origIdx = eventHist.event_history_size;
117 for (int idx = topSz; idx < size; idx++) {
118 Event evH = eventHist.events.get(--origIdx);
119 evH.base_info.idx = idx;
120 events.add(idx, evH);
121 }
122
123 description = eventHist.description;
124 event_history_size = size;
125 current_index = 0; // since it is full
126 full = true;
127 }
128
129 // Get an index for writing a new event. This method is synchronized for
130 // this event history infra. to be thread-safe. Once the index is obtained
131 // by the caller event at the index is updated without any lock
132 public synchronized int NextIdx() {
133 // curIdx should be in the 0 to evArraySz-1
134 if (current_index == (event_history_size-1)) {
135 current_index = 0;
136 full = true;
137 return (event_history_size-1);
138 } else {
139 current_index++;
140 return (current_index-1);
141 }
142 }
143
144 /**
145 * Add an event to the event history
146 * Eliminate java garbage cration by reusing the same object T
147 * Supplied object t is used to populate the event history array
148 * and the current object at that array location is returned to the
149 * calling process so that the calling process can use that object
150 * for the next event of the same type
151 * @param t
152 * @param op
153 * @return
154 */
155
156 public T put(T t, EvAction action) {
157 int idx = NextIdx();
158 Event evH = events.get(idx);
159 evH.base_info.state = EvState.BEING_MODIFIED;
160 evH.base_info.time_ms = System.currentTimeMillis();
161 evH.base_info.action = action;
162 T temp = evH.info;
163 evH.info = t;
164 evH.base_info.state = EvState.ACTIVE;
165 return temp;
166 }
167
168 /***
169 * Clear the event history, needs to be done under lock
170 */
171 public void clear() {
172 for (int idx = 0; idx < event_history_size; idx++) {
173 Event evH = events.get(idx);
174 evH.base_info.state = EvState.FREE;
175 current_index = 0;
176 full = false;
177 }
178 }
179}