blob: eb6feb1623e1e7bfd2f4bf9cc9caf12423f2c9b9 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 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 */
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070016package org.onlab.onos.store.intent.impl;
17
Thomas Vachuskab97cf282014-10-20 23:31:12 -070018import com.google.common.collect.ImmutableSet;
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070019import com.hazelcast.core.IMap;
20
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Service;
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070025import org.onlab.onos.net.intent.Intent;
26import org.onlab.onos.net.intent.IntentEvent;
27import org.onlab.onos.net.intent.IntentId;
28import org.onlab.onos.net.intent.IntentState;
29import org.onlab.onos.net.intent.IntentStore;
30import org.onlab.onos.net.intent.IntentStoreDelegate;
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070031import org.onlab.onos.store.hz.AbstractHazelcastStore;
32import org.onlab.onos.store.hz.SMap;
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070033import org.slf4j.Logger;
34
Thomas Vachuskab97cf282014-10-20 23:31:12 -070035import java.util.List;
36import java.util.Map;
37import java.util.concurrent.ConcurrentHashMap;
38
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070039import static com.google.common.base.Verify.verify;
Thomas Vachuskab97cf282014-10-20 23:31:12 -070040import static org.onlab.onos.net.intent.IntentState.*;
41import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070042
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070043@Component(immediate = true)
44@Service
45public class DistributedIntentStore
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070046 extends AbstractHazelcastStore<IntentEvent, IntentStoreDelegate>
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070047 implements IntentStore {
48
49 private final Logger log = getLogger(getClass());
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070050
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070051 // Assumption: IntentId will not have synonyms
52 private SMap<IntentId, Intent> intents;
53 private SMap<IntentId, IntentState> states;
54
55 // Map to store instance local intermediate state transition
56 private transient Map<IntentId, IntentState> transientStates = new ConcurrentHashMap<>();
57
58 private SMap<IntentId, List<Intent>> installable;
59
60 @Override
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070061 @Activate
62 public void activate() {
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070063 super.activate();
64
65 // TODO: enable near cache, allow read from backup for this IMap
66 IMap<byte[], byte[]> rawIntents = super.theInstance.getMap("intents");
67 intents = new SMap<>(rawIntents , super.serializer);
68
69 // TODO: disable near cache, disable read from backup for this IMap
70 IMap<byte[], byte[]> rawStates = super.theInstance.getMap("intent-states");
71 states = new SMap<>(rawStates , super.serializer);
72
73 transientStates.clear();
74
75 // TODO: disable near cache, disable read from backup for this IMap
76 IMap<byte[], byte[]> rawInstallables = super.theInstance.getMap("installable-intents");
77 installable = new SMap<>(rawInstallables , super.serializer);
78
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070079 log.info("Started");
80 }
81
82 @Deactivate
83 public void deactivate() {
84 log.info("Stopped");
85 }
86
87 @Override
88 public IntentEvent createIntent(Intent intent) {
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -070089 Intent existing = intents.putIfAbsent(intent.id(), intent);
90 if (existing != null) {
91 // duplicate, ignore
92 return null;
93 } else {
94 return this.setState(intent, IntentState.SUBMITTED);
95 }
Yuta HIGUCHI406a5652014-10-20 22:18:16 -070096 }
97
98 @Override
99 public IntentEvent removeIntent(IntentId intentId) {
100 Intent intent = intents.remove(intentId);
101 installable.remove(intentId);
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700102 if (intent == null) {
103 // was already removed
104 return null;
105 }
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700106 IntentEvent event = this.setState(intent, WITHDRAWN);
107 states.remove(intentId);
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700108 transientStates.remove(intentId);
109 // TODO: Should we callremoveInstalledIntents if this Intent was
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700110 return event;
111 }
112
113 @Override
114 public long getIntentCount() {
115 return intents.size();
116 }
117
118 @Override
119 public Iterable<Intent> getIntents() {
120 return ImmutableSet.copyOf(intents.values());
121 }
122
123 @Override
124 public Intent getIntent(IntentId intentId) {
125 return intents.get(intentId);
126 }
127
128 @Override
129 public IntentState getIntentState(IntentId id) {
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700130 final IntentState localState = transientStates.get(id);
131 if (localState != null) {
132 return localState;
133 }
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700134 return states.get(id);
135 }
136
137 @Override
138 public IntentEvent setState(Intent intent, IntentState state) {
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700139 final IntentId id = intent.id();
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700140 IntentEvent.Type type = null;
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700141 IntentState prev = null;
142 boolean transientStateChangeOnly = false;
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700143
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700144 // TODO: enable sanity checking if Debug enabled, etc.
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700145 switch (state) {
146 case SUBMITTED:
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700147 prev = states.putIfAbsent(id, SUBMITTED);
148 verify(prev == null, "Illegal state transition attempted from %s to SUBMITTED", prev);
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700149 type = IntentEvent.Type.SUBMITTED;
150 break;
151 case INSTALLED:
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700152 // parking state transition
153 prev = states.replace(id, INSTALLED);
154 verify(prev != null, "Illegal state transition attempted from non-SUBMITTED to INSTALLED");
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700155 type = IntentEvent.Type.INSTALLED;
156 break;
157 case FAILED:
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700158 prev = states.replace(id, FAILED);
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700159 type = IntentEvent.Type.FAILED;
160 break;
161 case WITHDRAWN:
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700162 prev = states.replace(id, WITHDRAWN);
163 verify(prev != null, "Illegal state transition attempted from non-WITHDRAWING to WITHDRAWN");
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700164 type = IntentEvent.Type.WITHDRAWN;
165 break;
166 default:
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700167 transientStateChangeOnly = true;
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700168 break;
169 }
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700170 if (!transientStateChangeOnly) {
171 log.debug("Parking State change: {} {}=>{}", id, prev, state);
172 }
173 // Update instance local state, which includes non-parking state transition
174 prev = transientStates.put(id, state);
175 log.debug("Transient State change: {} {}=>{}", id, prev, state);
176
Pavlin Radoslavovc8ccbd92014-10-22 09:59:37 -0700177 if (type == null) {
178 return null;
179 }
180 return new IntentEvent(type, intent);
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700181 }
182
183 @Override
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700184 public void setInstallableIntents(IntentId intentId, List<Intent> result) {
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700185 installable.put(intentId, result);
186 }
187
188 @Override
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700189 public List<Intent> getInstallableIntents(IntentId intentId) {
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700190 return installable.get(intentId);
191 }
192
193 @Override
194 public void removeInstalledIntents(IntentId intentId) {
195 installable.remove(intentId);
196 }
197
Yuta HIGUCHI10a31c32014-10-28 14:42:06 -0700198 // FIXME add handler to react to remote event
Yuta HIGUCHI406a5652014-10-20 22:18:16 -0700199}