blob: c1e610302292d1da764fc176d6983d792b29cd4b [file] [log] [blame]
Brian O'Connorb488b192015-02-06 17:58:58 -08001/*
2 * Copyright 2015 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.store.intent.impl;
17
18import com.google.common.collect.Maps;
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Service;
23import org.onosproject.net.intent.BatchWrite;
24import org.onosproject.net.intent.BatchWrite.Operation;
25import org.onosproject.net.intent.Intent;
26import org.onosproject.net.intent.IntentData;
27import org.onosproject.net.intent.IntentEvent;
Brian O'Connorb488b192015-02-06 17:58:58 -080028import org.onosproject.net.intent.IntentState;
29import org.onosproject.net.intent.IntentStore;
30import org.onosproject.net.intent.IntentStoreDelegate;
31import org.onosproject.net.intent.Key;
32import org.onosproject.store.AbstractStore;
Brian O'Connor2ba63fd2015-02-09 22:48:11 -080033import org.onosproject.store.impl.SystemClockTimestamp;
Brian O'Connorb488b192015-02-06 17:58:58 -080034import org.slf4j.Logger;
35
36import java.util.List;
37import java.util.Map;
Brian O'Connorb488b192015-02-06 17:58:58 -080038import java.util.stream.Collectors;
39
40import static com.google.common.base.Preconditions.checkNotNull;
41import static org.slf4j.LoggerFactory.getLogger;
42
Brian O'Connor2ba63fd2015-02-09 22:48:11 -080043//TODO Note: this store will be removed once the GossipIntentStore is stable
44
Brian O'Connorb488b192015-02-06 17:58:58 -080045@Component(immediate = true)
46@Service
47//FIXME remove this
48public class SimpleIntentStore
49 extends AbstractStore<IntentEvent, IntentStoreDelegate>
50 implements IntentStore {
51
52 private final Logger log = getLogger(getClass());
53
Brian O'Connorb488b192015-02-06 17:58:58 -080054 private final Map<Key, IntentData> current = Maps.newConcurrentMap();
Brian O'Connor2ba63fd2015-02-09 22:48:11 -080055 private final Map<Key, IntentData> pending = Maps.newConcurrentMap();
Brian O'Connorb488b192015-02-06 17:58:58 -080056
57 @Activate
58 public void activate() {
59 log.info("Started");
60 }
61
62 @Deactivate
63 public void deactivate() {
64 log.info("Stopped");
65 }
66
67 @Override
68 public long getIntentCount() {
69 return current.size();
70 }
71
72 @Override
73 public Iterable<Intent> getIntents() {
74 return current.values().stream()
75 .map(IntentData::intent)
76 .collect(Collectors.toList());
77 }
78
79 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -080080 public IntentState getIntentState(Key intentKey) {
81 IntentData data = current.get(intentKey);
82 return (data != null) ? data.state() : null;
Brian O'Connorb488b192015-02-06 17:58:58 -080083 }
84
85 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -080086 public List<Intent> getInstallableIntents(Key intentKey) {
87 // TODO: implement this or delete class
Brian O'Connorb488b192015-02-06 17:58:58 -080088 return null;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080089 /*
Brian O'Connorb488b192015-02-06 17:58:58 -080090 for (IntentData data : current.values()) {
91 if (Objects.equals(data.intent().id(), intentId)) {
92 return data.installables();
93 }
94 }
95 return null;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080096 */
Brian O'Connorb488b192015-02-06 17:58:58 -080097 }
98
99 /*
100 * Execute writes in a batch.
101 *
102 * @param batch BatchWrite to execute
103 * @return failed operations
104 */
105 @Override
106 public List<Operation> batchWrite(BatchWrite batch) {
107 throw new UnsupportedOperationException("deprecated");
108 /*
109 if (batch.isEmpty()) {
110 return Collections.emptyList();
111 }
112
113 List<Operation> failed = Lists.newArrayList();
114 for (Operation op : batch.operations()) {
115 switch (op.type()) {
116 case CREATE_INTENT:
117 checkArgument(op.args().size() == 1,
118 "CREATE_INTENT takes 1 argument. %s", op);
119 Intent intent = (Intent) op.args().get(0);
120 // TODO: what if it failed?
121// createIntent(intent); FIXME
122 break;
123
124 case REMOVE_INTENT:
125 checkArgument(op.args().size() == 1,
126 "REMOVE_INTENT takes 1 argument. %s", op);
127 IntentId intentId = (IntentId) op.args().get(0);
128// removeIntent(intentId); FIXME
129 break;
130
131 case REMOVE_INSTALLED:
132 checkArgument(op.args().size() == 1,
133 "REMOVE_INSTALLED takes 1 argument. %s", op);
134 intentId = (IntentId) op.args().get(0);
135 removeInstalledIntents(intentId);
136 break;
137
138 case SET_INSTALLABLE:
139 checkArgument(op.args().size() == 2,
140 "SET_INSTALLABLE takes 2 arguments. %s", op);
141 intentId = (IntentId) op.args().get(0);
142 @SuppressWarnings("unchecked")
143 List<Intent> installableIntents = (List<Intent>) op.args().get(1);
144 setInstallableIntents(intentId, installableIntents);
145 break;
146
147 case SET_STATE:
148 checkArgument(op.args().size() == 2,
149 "SET_STATE takes 2 arguments. %s", op);
150 intent = (Intent) op.args().get(0);
151 IntentState newState = (IntentState) op.args().get(1);
152 setState(intent, newState);
153 break;
154
155 default:
156 break;
157 }
158 }
159 return failed;
160 */
161 }
162
163 @Override
164 public void write(IntentData newData) {
Brian O'Connor2ba63fd2015-02-09 22:48:11 -0800165 synchronized (this) {
166 // TODO this could be refactored/cleaned up
167 IntentData currentData = current.get(newData.key());
168 IntentData pendingData = pending.get(newData.key());
169 if (currentData == null ||
170 // current version is less than or equal to newData's
171 // Note: current and newData's versions will be equal for state updates
172 currentData.version().compareTo(newData.version()) <= 0) {
173 current.put(newData.key(), newData);
174
175 if (pendingData != null
176 // pendingData version is less than or equal to newData's
177 // Note: a new update for this key could be pending (it's version will be greater)
178 && pendingData.version().compareTo(newData.version()) <= 0) {
179 pending.remove(newData.key());
180 }
181
182 try {
183 notifyDelegate(IntentEvent.getEvent(newData));
184 } catch (IllegalArgumentException e) {
185 //no-op
186 log.trace("ignore this exception: {}", e);
187 }
188 }
Brian O'Connorb488b192015-02-06 17:58:58 -0800189 }
190 }
191
192 @Override
193 public void batchWrite(Iterable<IntentData> updates) {
194 for (IntentData data : updates) {
195 write(data);
196 }
197 }
198
199 @Override
200 public Intent getIntent(Key key) {
201 IntentData data = current.get(key);
202 return (data != null) ? data.intent() : null;
203 }
204
Brian O'Connorb488b192015-02-06 17:58:58 -0800205 @Override
206 public void addPending(IntentData data) {
Brian O'Connor2ba63fd2015-02-09 22:48:11 -0800207 data.setVersion(new SystemClockTimestamp());
208 synchronized (this) {
209 IntentData existingData = pending.get(data.key());
210 if (existingData == null ||
211 // existing version is strictly less than data's version
212 // Note: if they are equal, we already have the update
213 // TODO maybe we should still make this <= to be safe?
214 existingData.version().compareTo(data.version()) < 0) {
215 pending.put(data.key(), data);
216 checkNotNull(delegate, "Store delegate is not set")
217 .process(data);
218 notifyDelegate(IntentEvent.getEvent(data));
219 } else {
220 log.debug("IntentData {} is older than existing: {}",
221 data, existingData);
222 }
223 //TODO consider also checking the current map at this point
224 }
Brian O'Connorb488b192015-02-06 17:58:58 -0800225 }
226
227
228 @Override
229 public boolean isMaster(Intent intent) {
230 return true;
231 }
232}