blob: cd802a68814395e23659109baf4529abfb4b6d6e [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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'Connorabafb502014-12-02 22:26:20 -080020import org.onosproject.net.intent.Intent;
Brian O'Connorcff03322015-02-03 15:28:59 -080021import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.net.intent.IntentEvent;
Brian O'Connor7775bda2015-02-06 15:01:18 -080023import org.onosproject.net.intent.IntentState;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.net.intent.IntentStore;
25import org.onosproject.net.intent.IntentStoreDelegate;
Ray Milkey5b3717e2015-02-05 11:44:08 -080026import org.onosproject.net.intent.Key;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.store.AbstractStore;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070028import org.osgi.service.component.annotations.Activate;
29import org.osgi.service.component.annotations.Component;
30import org.osgi.service.component.annotations.Deactivate;
Brian O'Connor66630c82014-10-02 21:08:19 -070031import org.slf4j.Logger;
32
Thomas Vachuskac96058a2014-10-20 23:00:16 -070033import java.util.List;
34import java.util.Map;
Brian O'Connorb499b352015-02-03 16:46:15 -080035import java.util.stream.Collectors;
Thomas Vachuskac96058a2014-10-20 23:00:16 -070036
Brian O'Connorb499b352015-02-03 16:46:15 -080037import static com.google.common.base.Preconditions.checkNotNull;
Brian O'Connora6c9b5c2015-04-29 22:38:29 -070038import static org.onosproject.net.intent.IntentState.PURGE_REQ;
Thomas Vachuskac96058a2014-10-20 23:00:16 -070039import static org.slf4j.LoggerFactory.getLogger;
Brian O'Connor66630c82014-10-02 21:08:19 -070040
Jonathan Hart0d18df32015-03-21 08:42:59 -070041/**
42 * Simple single-instance implementation of the intent store.
43 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070044@Component(immediate = true, service = IntentStore.class)
Brian O'Connor66630c82014-10-02 21:08:19 -070045public class SimpleIntentStore
tom85258ee2014-10-07 00:10:02 -070046 extends AbstractStore<IntentEvent, IntentStoreDelegate>
47 implements IntentStore {
Brian O'Connor66630c82014-10-02 21:08:19 -070048
49 private final Logger log = getLogger(getClass());
Brian O'Connorcff03322015-02-03 15:28:59 -080050
Ray Milkey5b3717e2015-02-05 11:44:08 -080051 private final Map<Key, IntentData> current = Maps.newConcurrentMap();
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -080052 private final Map<Key, IntentData> pending = Maps.newConcurrentMap();
53
Brian O'Connor66630c82014-10-02 21:08:19 -070054 @Activate
55 public void activate() {
56 log.info("Started");
57 }
58
59 @Deactivate
60 public void deactivate() {
61 log.info("Stopped");
62 }
63
Brian O'Connor66630c82014-10-02 21:08:19 -070064 @Override
65 public long getIntentCount() {
Brian O'Connorb499b352015-02-03 16:46:15 -080066 return current.size();
Brian O'Connor66630c82014-10-02 21:08:19 -070067 }
68
69 @Override
70 public Iterable<Intent> getIntents() {
Brian O'Connorb499b352015-02-03 16:46:15 -080071 return current.values().stream()
72 .map(IntentData::intent)
73 .collect(Collectors.toList());
Brian O'Connor66630c82014-10-02 21:08:19 -070074 }
75
76 @Override
Brian O'Connora6c9b5c2015-04-29 22:38:29 -070077 public Iterable<IntentData> getIntentData(boolean localOnly, long olderThan) {
78 if (localOnly || olderThan > 0) {
79 long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
80 final SystemClockTimestamp time = new SystemClockTimestamp(older);
Brian O'Connoreba4e342015-04-30 22:50:13 -070081 return current.values().stream()
Brian O'Connora6c9b5c2015-04-29 22:38:29 -070082 .filter(data -> data.version().isOlderThan(time) &&
83 (!localOnly || isMaster(data.key())))
Brian O'Connor3c58e962015-04-28 23:21:51 -070084 .collect(Collectors.toList());
85 }
86 return Lists.newArrayList(current.values());
87 }
88
89 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -080090 public IntentState getIntentState(Key intentKey) {
91 IntentData data = current.get(intentKey);
92 return (data != null) ? data.state() : null;
Brian O'Connor7775bda2015-02-06 15:01:18 -080093 }
94
95 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -080096 public List<Intent> getInstallableIntents(Key intentKey) {
97 IntentData data = current.get(intentKey);
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -080098 if (data != null) {
99 return data.installables();
100 }
101 return null;
102 }
103
Brian O'Connorcff03322015-02-03 15:28:59 -0800104 @Override
Brian O'Connor03406a42015-02-03 17:28:57 -0800105 public void write(IntentData newData) {
Jonathan Hart0d18df32015-03-21 08:42:59 -0700106 checkNotNull(newData);
107
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800108 synchronized (this) {
109 // TODO this could be refactored/cleaned up
110 IntentData currentData = current.get(newData.key());
111 IntentData pendingData = pending.get(newData.key());
112
Jonathan Hart72175c22015-03-24 18:55:58 -0700113 if (IntentData.isUpdateAcceptable(currentData, newData)) {
Ray Milkey77a455f2015-03-27 10:08:17 -0700114 if (pendingData != null) {
115 if (pendingData.state() == PURGE_REQ) {
116 current.remove(newData.key(), newData);
117 } else {
Yuta HIGUCHI4f8a3772017-05-16 20:23:49 -0700118 current.put(newData.key(), IntentData.copy(newData));
Ray Milkey77a455f2015-03-27 10:08:17 -0700119 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800120
Ray Milkey77a455f2015-03-27 10:08:17 -0700121 if (pendingData.version().compareTo(newData.version()) <= 0) {
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800122 // pendingData version is less than or equal to newData's
123 // Note: a new update for this key could be pending (it's version will be greater)
Ray Milkey77a455f2015-03-27 10:08:17 -0700124 pending.remove(newData.key());
125 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800126 }
Sho SHIMIZU96b39e22016-01-15 17:35:04 -0800127 IntentEvent.getEvent(newData).ifPresent(this::notifyDelegate);
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800128 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800129 }
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800130 }
131
Brian O'Connor03406a42015-02-03 17:28:57 -0800132 @Override
133 public void batchWrite(Iterable<IntentData> updates) {
134 for (IntentData data : updates) {
135 write(data);
136 }
137 }
138
Brian O'Connor7775bda2015-02-06 15:01:18 -0800139 @Override
140 public Intent getIntent(Key key) {
141 IntentData data = current.get(key);
142 return (data != null) ? data.intent() : null;
143 }
144
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800145 @Override
146 public IntentData getIntentData(Key key) {
Jonathan Hart0d18df32015-03-21 08:42:59 -0700147 IntentData currentData = current.get(key);
148 if (currentData == null) {
149 return null;
150 }
Yuta HIGUCHI4f8a3772017-05-16 20:23:49 -0700151 return IntentData.copy(currentData);
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800152 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800153
154 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800155 public void addPending(IntentData data) {
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800156 if (data.version() == null) { // recompiled intents will already have a version
Sho SHIMIZU2f26fb22016-01-19 14:04:46 -0800157 data = new IntentData(data.intent(), data.state(), new SystemClockTimestamp());
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800158 }
159 synchronized (this) {
160 IntentData existingData = pending.get(data.key());
161 if (existingData == null ||
162 // existing version is strictly less than data's version
163 // Note: if they are equal, we already have the update
164 // TODO maybe we should still make this <= to be safe?
165 existingData.version().compareTo(data.version()) < 0) {
166 pending.put(data.key(), data);
167 checkNotNull(delegate, "Store delegate is not set")
Yuta HIGUCHI4f8a3772017-05-16 20:23:49 -0700168 .process(IntentData.copy(data));
Sho SHIMIZU96b39e22016-01-15 17:35:04 -0800169 IntentEvent.getEvent(data).ifPresent(this::notifyDelegate);
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800170 } else {
171 log.debug("IntentData {} is older than existing: {}",
172 data, existingData);
173 }
174 //TODO consider also checking the current map at this point
175 }
Brian O'Connorcff03322015-02-03 15:28:59 -0800176 }
Brian O'Connorcff03322015-02-03 15:28:59 -0800177
Jonathan Hart6a8fd1d2015-02-25 15:44:37 -0800178 @Override
179 public boolean isMaster(Key intentKey) {
180 return true;
181 }
182
183 @Override
184 public Iterable<Intent> getPending() {
185 return pending.values().stream()
186 .map(IntentData::intent)
187 .collect(Collectors.toList());
188 }
Brian O'Connora6c9b5c2015-04-29 22:38:29 -0700189
190 @Override
191 public Iterable<IntentData> getPendingData() {
192 return Lists.newArrayList(pending.values());
193 }
194
195 @Override
Brian O'Connorc590ebb2016-12-08 18:16:41 -0800196 public IntentData getPendingData(Key intentKey) {
197 return pending.get(intentKey);
198 }
199
200 @Override
Brian O'Connora6c9b5c2015-04-29 22:38:29 -0700201 public Iterable<IntentData> getPendingData(boolean localOnly, long olderThan) {
202 long older = System.nanoTime() - olderThan * 1_000_000; //convert ms to ns
203 final SystemClockTimestamp time = new SystemClockTimestamp(older);
204 return pending.values().stream()
205 .filter(data -> data.version().isOlderThan(time) &&
206 (!localOnly || isMaster(data.key())))
207 .collect(Collectors.toList());
208 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700209}