blob: e72cb13d4fe27deadb8349c3630066acaaed76bc [file] [log] [blame]
Jonathan Hartaa380972014-04-03 10:24:46 -07001package net.onrc.onos.core.intent;
Toshio Koideb609b3b2014-02-14 18:25:52 -08002
3import java.util.Collection;
4import java.util.EventListener;
5import java.util.HashMap;
6import java.util.HashSet;
Toshio Koideb609b3b2014-02-14 18:25:52 -08007import java.util.LinkedList;
Toshio Koideb609b3b2014-02-14 18:25:52 -08008import java.util.Map.Entry;
9
Jonathan Hartaa380972014-04-03 10:24:46 -070010import net.onrc.onos.core.intent.Intent.IntentState;
11import net.onrc.onos.core.intent.runtime.IntentStateList;
Ray Milkey0b122ed2014-04-14 10:06:03 -070012import org.slf4j.Logger;
13import org.slf4j.LoggerFactory;
Toshio Koideb609b3b2014-02-14 18:25:52 -080014
15/**
16 * @author Toshio Koide (t-koide@onlab.us)
17 */
18public class IntentMap {
Ray Milkey269ffb92014-04-03 14:43:30 -070019 private HashSet<ChangedListener> listeners = new HashSet<>();
20 private HashMap<String, Intent> intents = new HashMap<>();
21 private LinkedList<ChangedEvent> events = new LinkedList<>();
Ray Milkey0b122ed2014-04-14 10:06:03 -070022 private static final Logger log = LoggerFactory.getLogger(IntentMap.class);
Toshio Koidedf2eab92014-02-20 11:24:59 -080023
Ray Milkey269ffb92014-04-03 14:43:30 -070024 public enum ChangedEventType {
25 /**
26 * Added new intent.
27 */
28 ADDED,
Toshio Koideb609b3b2014-02-14 18:25:52 -080029
Ray Milkey269ffb92014-04-03 14:43:30 -070030 /**
31 * Removed existing intent.
32 * The specified intent is an instance of Intent class (not a child class)
33 * Only id and state are valid.
34 */
35 REMOVED,
Toshio Koideb609b3b2014-02-14 18:25:52 -080036
Ray Milkey269ffb92014-04-03 14:43:30 -070037 /**
38 * Changed state of existing intent.
39 * The specified intent is an instance of Intent class (not a child class)
40 * Only id and state are valid.
41 */
42 STATE_CHANGED,
43 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080044
Pavlin Radoslavovfee80982014-04-10 12:12:04 -070045 public static class ChangedEvent {
Ray Milkey269ffb92014-04-03 14:43:30 -070046 public ChangedEvent(ChangedEventType eventType, Intent intent) {
47 this.eventType = eventType;
48 this.intent = intent;
49 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080050
Ray Milkey269ffb92014-04-03 14:43:30 -070051 public ChangedEventType eventType;
52 public Intent intent;
Pavlin Radoslavovb6309292014-04-11 03:25:47 -070053
54 /**
55 * Get a string representation of the object.
56 * <p/>
57 * The string has the following form:
58 * [eventType=XXX intent=XXX]
59 *
60 * @return a string representation of the object.
61 */
62 @Override
63 public String toString() {
64 StringBuilder ret = new StringBuilder();
65 ret.append("[eventType=");
66 ret.append(this.eventType.toString());
67 ret.append(" intent=");
68 ret.append(this.intent.toString());
69 ret.append("]");
70 return ret.toString();
71 }
Ray Milkey269ffb92014-04-03 14:43:30 -070072 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080073
Ray Milkey269ffb92014-04-03 14:43:30 -070074 public interface ChangedListener extends EventListener {
75 void intentsChange(LinkedList<ChangedEvent> events);
76 }
Toshio Koideb609b3b2014-02-14 18:25:52 -080077
Ray Milkey269ffb92014-04-03 14:43:30 -070078 //================================================================================
79 // public methods
80 //================================================================================
Toshio Koideb609b3b2014-02-14 18:25:52 -080081
Ray Milkey269ffb92014-04-03 14:43:30 -070082 public void executeOperations(IntentOperationList operations) {
83 for (IntentOperation operation : operations) {
84 switch (operation.operator) {
85 case ADD:
86 handleAddOperation(operation);
87 break;
88 case REMOVE:
89 handleRemoveOperation(operation);
90 break;
91 case ERROR:
92 handleErrorOperation(operation);
93 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -070094 default:
95 log.error("Unknown intent operation {}", operation.operator);
96 break;
Ray Milkey269ffb92014-04-03 14:43:30 -070097 }
98 }
99 notifyEvents();
100 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800101
Ray Milkey269ffb92014-04-03 14:43:30 -0700102 public void purge() {
103 LinkedList<String> removeIds = new LinkedList<>();
104 for (Entry<String, Intent> entry : intents.entrySet()) {
105 Intent intent = entry.getValue();
106 if (intent.getState() == IntentState.DEL_ACK
107 || intent.getState() == IntentState.INST_NACK) {
108 removeIds.add(intent.getId());
109 }
110 }
111 for (String intentId : removeIds) {
112 removeIntent(intentId);
113 }
114 notifyEvents();
115 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800116
Ray Milkey269ffb92014-04-03 14:43:30 -0700117 public void changeStates(IntentStateList states) {
118 for (Entry<String, IntentState> state : states.entrySet()) {
119 setState(state.getKey(), state.getValue());
120 }
121 notifyEvents();
122 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800123
Ray Milkey269ffb92014-04-03 14:43:30 -0700124 public Intent getIntent(String intentId) {
125 return intents.get(intentId);
126 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800127
Ray Milkey269ffb92014-04-03 14:43:30 -0700128 public Collection<Intent> getAllIntents() {
129 return intents.values();
130 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800131
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 public void addChangeListener(ChangedListener listener) {
133 listeners.add(listener);
134 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800135
Ray Milkey269ffb92014-04-03 14:43:30 -0700136 public void removeChangedListener(ChangedListener listener) {
137 listeners.remove(listener);
138 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800139
Ray Milkey269ffb92014-04-03 14:43:30 -0700140 //================================================================================
141 // methods that affect intents map (protected)
142 //================================================================================
Toshio Koidedf2eab92014-02-20 11:24:59 -0800143
Ray Milkey269ffb92014-04-03 14:43:30 -0700144 protected void putIntent(Intent intent) {
Ray Milkeyb29e6262014-04-09 16:02:14 -0700145 if (intents.containsKey(intent.getId())) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700146 removeIntent(intent.getId());
Ray Milkeyb29e6262014-04-09 16:02:14 -0700147 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700148 intents.put(intent.getId(), intent);
149 events.add(new ChangedEvent(ChangedEventType.ADDED, intent));
150 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800151
Ray Milkey269ffb92014-04-03 14:43:30 -0700152 protected void removeIntent(String intentId) {
153 Intent intent = intents.remove(intentId);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700154 if (intent == null) {
155 return;
156 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700157 events.add(new ChangedEvent(ChangedEventType.REMOVED, intent));
158 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800159
Ray Milkey269ffb92014-04-03 14:43:30 -0700160 protected void setState(String intentId, IntentState state) {
161 Intent intent = intents.get(intentId);
Ray Milkeyb29e6262014-04-09 16:02:14 -0700162 if (intent == null) {
163 return;
164 }
Ray Milkey269ffb92014-04-03 14:43:30 -0700165 intent.setState(state);
166 events.add(new ChangedEvent(ChangedEventType.STATE_CHANGED, intent));
167 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800168
Ray Milkey269ffb92014-04-03 14:43:30 -0700169 //================================================================================
170 // helper methods (protected)
171 //================================================================================
Toshio Koidedf2eab92014-02-20 11:24:59 -0800172
Ray Milkey269ffb92014-04-03 14:43:30 -0700173 protected void handleAddOperation(IntentOperation operation) {
174 putIntent(operation.intent);
175 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800176
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 protected void handleRemoveOperation(IntentOperation operation) {
178 Intent intent = getIntent(operation.intent.getId());
179 if (intent == null) {
180 // TODO error handling
Ray Milkey1aa71f82014-04-08 16:23:24 -0700181 return;
Ray Milkey269ffb92014-04-03 14:43:30 -0700182 } else {
183 setState(intent.getId(), IntentState.DEL_REQ);
184 }
185 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800186
Ray Milkey269ffb92014-04-03 14:43:30 -0700187 protected void handleErrorOperation(IntentOperation operation) {
188 //TODO put error message into the intent
Toshio Koidedf2eab92014-02-20 11:24:59 -0800189
Ray Milkey269ffb92014-04-03 14:43:30 -0700190 ErrorIntent errorIntent = (ErrorIntent) operation.intent;
191 Intent targetIntent = intents.get(errorIntent.getId());
192 if (targetIntent == null) {
193 // TODO error handling
194 return;
195 }
Toshio Koidedf2eab92014-02-20 11:24:59 -0800196
Ray Milkey269ffb92014-04-03 14:43:30 -0700197 switch (targetIntent.getState()) {
198 case CREATED:
199 case INST_REQ:
200 case INST_ACK:
201 case REROUTE_REQ:
202 setState(targetIntent.getId(), IntentState.INST_NACK);
203 break;
204 case DEL_REQ:
205 setState(targetIntent.getId(), IntentState.DEL_PENDING);
206 break;
207 case INST_NACK:
208 case DEL_PENDING:
209 case DEL_ACK:
210 // do nothing
211 break;
Ray Milkey0b122ed2014-04-14 10:06:03 -0700212 default:
213 log.error("Unknown intent state {}", targetIntent.getState());
214 break;
Ray Milkey269ffb92014-04-03 14:43:30 -0700215 }
216 }
217
218 protected void notifyEvents() {
219 for (ChangedListener listener : listeners) {
220 listener.intentsChange(events);
221 }
222 events.clear();
223 }
Toshio Koideb609b3b2014-02-14 18:25:52 -0800224}