blob: 9f959663c265746c7c1a13b2c6f2e7587a0506ee [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -08002 * Copyright 2015 Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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 */
Thomas Vachuskac97aa612015-06-23 16:00:18 -070016package org.onosproject.store.trivial;
Brian O'Connor66630c82014-10-02 21:08:19 -070017
Brian O'Connor3c58e962015-04-28 23:21:51 -070018import com.google.common.collect.Lists;
Brian O'Connorb499b352015-02-03 16:46:15 -080019import com.google.common.collect.Maps;
Brian O'Connor66630c82014-10-02 21:08:19 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.net.intent.Intent;
Brian O'Connorcff03322015-02-03 15:28:59 -080025import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.net.intent.IntentEvent;
Brian O'Connor7775bda2015-02-06 15:01:18 -080027import org.onosproject.net.intent.IntentState;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.intent.IntentStore;
29import org.onosproject.net.intent.IntentStoreDelegate;
Ray Milkey5b3717e2015-02-05 11:44:08 -080030import org.onosproject.net.intent.Key;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.store.AbstractStore;
Brian O'Connor66630c82014-10-02 21:08:19 -070032import org.slf4j.Logger;
33
Thomas Vachuskac96058a2014-10-20 23:00:16 -070034import java.util.List;
35import java.util.Map;
Brian O'Connorb499b352015-02-03 16:46:15 -080036import java.util.stream.Collectors;
Thomas Vachuskac96058a2014-10-20 23:00:16 -070037
Brian O'Connorb499b352015-02-03 16:46:15 -080038import static com.google.common.base.Preconditions.checkNotNull;
Brian O'Connora6c9b5c2015-04-29 22:38:29 -070039import static org.onosproject.net.intent.IntentState.PURGE_REQ;
Thomas Vachuskac96058a2014-10-20 23:00:16 -070040import static org.slf4j.LoggerFactory.getLogger;
Brian O'Connor66630c82014-10-02 21:08:19 -070041
Jonathan Hart0d18df32015-03-21 08:42:59 -070042/**
43 * Simple single-instance implementation of the intent store.
44 */
Brian O'Connor66630c82014-10-02 21:08:19 -070045@Component(immediate = true)
46@Service
47public class SimpleIntentStore
tom85258ee2014-10-07 00:10:02 -070048 extends AbstractStore<IntentEvent, IntentStoreDelegate>
49 implements IntentStore {
Brian O'Connor66630c82014-10-02 21:08:19 -070050
51 private final Logger log = getLogger(getClass());
Brian O'Connorcff03322015-02-03 15:28:59 -080052
Ray Milkey5b3717e2015-02-05 11:44:08 -080053 private final Map<Key, IntentData> current = Maps.newConcurrentMap();
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -080054 private final Map<Key, IntentData> pending = Maps.newConcurrentMap();
55
Brian O'Connor66630c82014-10-02 21:08:19 -070056 @Activate
57 public void activate() {
58 log.info("Started");
59 }
60
61 @Deactivate
62 public void deactivate() {
63 log.info("Stopped");
64 }
65
Brian O'Connor66630c82014-10-02 21:08:19 -070066 @Override
67 public long getIntentCount() {
Brian O'Connorb499b352015-02-03 16:46:15 -080068 return current.size();
Brian O'Connor66630c82014-10-02 21:08:19 -070069 }
70
71 @Override
72 public Iterable<Intent> getIntents() {
Brian O'Connorb499b352015-02-03 16:46:15 -080073 return current.values().stream()
74 .map(IntentData::intent)
75 .collect(Collectors.toList());
Brian O'Connor66630c82014-10-02 21:08:19 -070076 }
77
78 @Override
Brian O'Connora6c9b5c2015-04-29 22:38:29 -070079 public Iterable<IntentData> getIntentData(boolean localOnly, long olderThan) {
80 if (localOnly || olderThan > 0) {
81 long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
82 final SystemClockTimestamp time = new SystemClockTimestamp(older);
Brian O'Connoreba4e342015-04-30 22:50:13 -070083 return current.values().stream()
Brian O'Connora6c9b5c2015-04-29 22:38:29 -070084 .filter(data -> data.version().isOlderThan(time) &&
85 (!localOnly || isMaster(data.key())))
Brian O'Connor3c58e962015-04-28 23:21:51 -070086 .collect(Collectors.toList());
87 }
88 return Lists.newArrayList(current.values());
89 }
90
91 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -080092 public IntentState getIntentState(Key intentKey) {
93 IntentData data = current.get(intentKey);
94 return (data != null) ? data.state() : null;
Brian O'Connor7775bda2015-02-06 15:01:18 -080095 }
96
97 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -080098 public List<Intent> getInstallableIntents(Key intentKey) {
99 IntentData data = current.get(intentKey);
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800100 if (data != null) {
101 return data.installables();
102 }
103 return null;
104 }
105
Brian O'Connorcff03322015-02-03 15:28:59 -0800106 @Override
Brian O'Connor03406a42015-02-03 17:28:57 -0800107 public void write(IntentData newData) {
Jonathan Hart0d18df32015-03-21 08:42:59 -0700108 checkNotNull(newData);
109
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800110 synchronized (this) {
111 // TODO this could be refactored/cleaned up
112 IntentData currentData = current.get(newData.key());
113 IntentData pendingData = pending.get(newData.key());
114
Jonathan Hart72175c22015-03-24 18:55:58 -0700115 if (IntentData.isUpdateAcceptable(currentData, newData)) {
Ray Milkey77a455f2015-03-27 10:08:17 -0700116 if (pendingData != null) {
117 if (pendingData.state() == PURGE_REQ) {
118 current.remove(newData.key(), newData);
119 } else {
120 current.put(newData.key(), new IntentData(newData));
121 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800122
Ray Milkey77a455f2015-03-27 10:08:17 -0700123 if (pendingData.version().compareTo(newData.version()) <= 0) {
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800124 // pendingData version is less than or equal to newData's
125 // Note: a new update for this key could be pending (it's version will be greater)
Ray Milkey77a455f2015-03-27 10:08:17 -0700126 pending.remove(newData.key());
127 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800128 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800129 notifyDelegateIfNotNull(IntentEvent.getEvent(newData));
130 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800131 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800132 }
133
134 private void notifyDelegateIfNotNull(IntentEvent event) {
135 if (event != null) {
136 notifyDelegate(event);
Brian O'Connor03406a42015-02-03 17:28:57 -0800137 }
138 }
139
140 @Override
141 public void batchWrite(Iterable<IntentData> updates) {
142 for (IntentData data : updates) {
143 write(data);
144 }
145 }
146
Brian O'Connor7775bda2015-02-06 15:01:18 -0800147 @Override
148 public Intent getIntent(Key key) {
149 IntentData data = current.get(key);
150 return (data != null) ? data.intent() : null;
151 }
152
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800153 @Override
154 public IntentData getIntentData(Key key) {
Jonathan Hart0d18df32015-03-21 08:42:59 -0700155 IntentData currentData = current.get(key);
156 if (currentData == null) {
157 return null;
158 }
159 return new IntentData(currentData);
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800160 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800161
162 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800163 public void addPending(IntentData data) {
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800164 if (data.version() == null) { // recompiled intents will already have a version
165 data.setVersion(new SystemClockTimestamp());
166 }
167 synchronized (this) {
168 IntentData existingData = pending.get(data.key());
169 if (existingData == null ||
170 // existing version is strictly less than data's version
171 // Note: if they are equal, we already have the update
172 // TODO maybe we should still make this <= to be safe?
173 existingData.version().compareTo(data.version()) < 0) {
174 pending.put(data.key(), data);
175 checkNotNull(delegate, "Store delegate is not set")
Brian O'Connoreba4e342015-04-30 22:50:13 -0700176 .process(new IntentData(data));
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800177 notifyDelegateIfNotNull(IntentEvent.getEvent(data));
178 } else {
179 log.debug("IntentData {} is older than existing: {}",
180 data, existingData);
181 }
182 //TODO consider also checking the current map at this point
183 }
Brian O'Connorcff03322015-02-03 15:28:59 -0800184 }
Brian O'Connorcff03322015-02-03 15:28:59 -0800185
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800186 @Override
187 public boolean isMaster(Key intentKey) {
188 return true;
189 }
190
191 @Override
192 public Iterable<Intent> getPending() {
193 return pending.values().stream()
194 .map(IntentData::intent)
195 .collect(Collectors.toList());
196 }
Brian O'Connora6c9b5c2015-04-29 22:38:29 -0700197
198 @Override
199 public Iterable<IntentData> getPendingData() {
200 return Lists.newArrayList(pending.values());
201 }
202
203 @Override
204 public Iterable<IntentData> getPendingData(boolean localOnly, long olderThan) {
205 long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
206 final SystemClockTimestamp time = new SystemClockTimestamp(older);
207 return pending.values().stream()
208 .filter(data -> data.version().isOlderThan(time) &&
209 (!localOnly || isMaster(data.key())))
210 .collect(Collectors.toList());
211 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700212}