blob: c9151ded69991a18e18748dd868d316e37db49c5 [file] [log] [blame]
Jonathan Hart6df90172014-04-03 10:13:11 -07001package net.onrc.onos.core.datastore.topology;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -07002
3import java.nio.ByteBuffer;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.Map;
7
Jonathan Hart6df90172014-04-03 10:13:11 -07008import net.onrc.onos.core.datastore.DataStoreClient;
9import net.onrc.onos.core.datastore.IKVTable.IKVEntry;
Yuta HIGUCHI1cd90292014-04-03 14:31:10 -070010import net.onrc.onos.core.datastore.serializers.Topology.SwitchProperty;
Jonathan Hart6df90172014-04-03 10:13:11 -070011import net.onrc.onos.core.datastore.utils.KVObject;
Jonathan Hart472062d2014-04-03 10:56:48 -070012import net.onrc.onos.core.topology.SwitchEvent;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070013
14import org.slf4j.Logger;
15import org.slf4j.LoggerFactory;
16
17import com.esotericsoftware.kryo.Kryo;
18import com.google.protobuf.ByteString;
19import com.google.protobuf.InvalidProtocolBufferException;
20
21/**
22 * Switch object in data store.
Ray Milkey269ffb92014-04-03 14:43:30 -070023 * <p/>
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070024 * Note: This class will not maintain invariants.
Ray Milkey269ffb92014-04-03 14:43:30 -070025 * e.g., It will NOT automatically remove Ports on Switch,
26 * when deleting a Switch.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070027 */
28public class KVSwitch extends KVObject {
29 private static final Logger log = LoggerFactory.getLogger(KVSwitch.class);
30
Ray Milkey5c9f2db2014-04-09 10:31:21 -070031 private static final ThreadLocal<Kryo> SWITCH_KRYO = new ThreadLocal<Kryo>() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070032 @Override
33 protected Kryo initialValue() {
34 Kryo kryo = new Kryo();
35 kryo.setRegistrationRequired(true);
36 kryo.setReferences(false);
37 kryo.register(byte[].class);
38 kryo.register(byte[][].class);
39 kryo.register(HashMap.class);
40 // TODO check if we should explicitly specify EnumSerializer
41 kryo.register(STATUS.class);
42 return kryo;
43 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070044 };
45
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070046 static final String SWITCH_TABLE_SUFFIX = ":Switch";
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070047
48 // must not re-order enum members, ordinal will be sent over wire
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070049 /**
50 * Status.
51 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070052 public enum STATUS {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070053 INACTIVE, ACTIVE;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070054 }
55
56 private final Long dpid;
57 private STATUS status;
58
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070059 /**
60 * Generate a SwitchID from dpid.
61 *
62 * @param dpid dpid of the switch
63 * @return SwitchID
64 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070065 public static byte[] getSwitchID(final Long dpid) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070066 return SwitchEvent.getSwitchID(dpid).array();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070067 }
68
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070069 /**
70 * Gets the DPID from SwitchID.
71 *
72 * @param key SwitchID
73 * @return dpid
74 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070075 public static long getDpidFromKey(final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070076 return getDpidFromKey(ByteBuffer.wrap(key));
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070077 }
78
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070079 /**
80 * Gets the DPID from SwitchID.
81 *
82 * @param keyBuf SwitchID
83 * @return dpid
84 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070085 public static long getDpidFromKey(final ByteBuffer keyBuf) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070086 if (keyBuf.getChar() != 'S') {
87 throw new IllegalArgumentException("Invalid Switch key");
88 }
89 return keyBuf.getLong();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070090 }
91
Yuta HIGUCHIcc561882014-05-22 10:31:32 -070092 // FIXME Should the parameter be DPID here, or should caller specify the key?
93 // Should layer above have the control of the ID computation/generation?
94 /**
95 * KVSwitch constructor for default namespace.
96 *
97 * @param dpid dpid of this switch
98 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070099 public KVSwitch(final Long dpid) {
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700100 this(dpid, KVObject.DEFAULT_NAMESPACE);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700101 }
102
103 /**
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700104 * KVSwitch constructor for specified namespace.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700105 *
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700106 * @param dpid dpid of this switch
107 * @param namespace namespace to create this object
108 */
109 public KVSwitch(final Long dpid, final String namespace) {
110 super(DataStoreClient.getClient()
111 .getTable(namespace + SWITCH_TABLE_SUFFIX),
112 getSwitchID(dpid), namespace);
113
114 this.dpid = dpid;
115 this.status = STATUS.INACTIVE;
116 // may need to store namespace here or at KVObject.
117 }
118
119 /**
120 * Gets an instance from SwitchID in default namespace.
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700121 * <p/>
122 * Note: You need to call `read()` to get the DB content.
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700123 *
124 * @param key SwitchID
125 * @return {@link KVSwitch} instance
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700126 */
127 public static KVSwitch createFromKey(final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700128 return new KVSwitch(getDpidFromKey(key));
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700129 }
130
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700131 /**
132 * Gets an instance from SwitchID in specified namespace.
Jonathan Hart99ff20a2014-06-15 16:53:00 -0700133 * <p/>
134 * Note: You need to call `read()` to get the DB content.
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700135 *
136 * @param key SwitchID
137 * @param namespace namespace to create this object
138 * @return {@link KVSwitch} instance
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700139 */
140 public static KVSwitch createFromKey(final byte[] key, final String namespace) {
141 return new KVSwitch(getDpidFromKey(key), namespace);
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700142 }
143
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700144 /**
145 * Gets all the switches in default namespace.
146 *
147 * @return All the {@link KVSwitch}
148 */
149 public static Iterable<KVSwitch> getAllSwitches() {
150 return getAllSwitches(DEFAULT_NAMESPACE);
151 }
152
153 /**
154 * Gets all the switches in specified namespace.
155 *
156 * @param namespace Namespace to get all switches.
157 * @return All the {@link KVSwitch}
158 */
159 public static Iterable<KVSwitch> getAllSwitches(final String namespace) {
160 return new SwitchEnumerator(namespace);
161 }
162
163 /**
164 * Utility class to provide Iterable interface.
165 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700166 public static class SwitchEnumerator implements Iterable<KVSwitch> {
167
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700168 private final String namespace;
169
170 /**
171 * Constructor to iterate Ports in specified namespace.
172 *
173 * @param namespace namespace to iterate through
174 */
175 public SwitchEnumerator(final String namespace) {
176 this.namespace = namespace;
177 }
178
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700179 @Override
180 public Iterator<KVSwitch> iterator() {
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700181 return new SwitchIterator(namespace);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700182 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700183 }
184
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700185 /**
186 * Utility class to provide Iterator over all the Switch objects.
187 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700188 public static class SwitchIterator extends AbstractObjectIterator<KVSwitch> {
189
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700190 /**
191 * Constructor to create an iterator to iterate all the Switches
192 * in specified namespace.
193 *
194 * @param namespace namespace to iterate through
195 */
196 public SwitchIterator(final String namespace) {
197 super(DataStoreClient.getClient()
198 .getTable(namespace + SWITCH_TABLE_SUFFIX), namespace);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700199 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700200
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700201 @Override
202 public KVSwitch next() {
203 IKVEntry o = enumerator.next();
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700204 KVSwitch e = KVSwitch.createFromKey(o.getKey(), namespace);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700205 e.deserialize(o.getValue(), o.getVersion());
206 return e;
207 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700208 }
209
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700210 /**
211 * Gets the status.
212 *
213 * @return status
214 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700215 public STATUS getStatus() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700216 return status;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700217 }
218
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700219 /**
220 * Sets the status.
221 *
222 * @param status new status
223 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700224 public void setStatus(final STATUS status) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700225 this.status = status;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700226 }
227
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700228 /**
229 * Gets the DPID of the switch this port is on.
230 *
231 * @return DPID of the switch this port is on
232 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700233 public Long getDpid() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700234 return dpid;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700235 }
236
Yuta HIGUCHIcc561882014-05-22 10:31:32 -0700237 /**
238 * Gets the SwitchID.
239 *
240 * @return SwitchID
241 */
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700242 public byte[] getId() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700243 return getKey();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700244 }
245
246 @Override
247 public byte[] serialize() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700248 Map<Object, Object> map = getPropertyMap();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700249
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700250 SwitchProperty.Builder sw = SwitchProperty.newBuilder();
251 sw.setDpid(dpid);
252 sw.setStatus(status.ordinal());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700253
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700254 if (!map.isEmpty()) {
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700255 byte[] propMaps = serializePropertyMap(SWITCH_KRYO.get(), map);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700256 sw.setValue(ByteString.copyFrom(propMaps));
257 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700258
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700259 return sw.build().toByteArray();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700260 }
261
262 @Override
263 protected boolean deserialize(final byte[] bytes) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700264 try {
265 boolean success = true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700266
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700267 SwitchProperty sw = SwitchProperty.parseFrom(bytes);
268 byte[] props = sw.getValue().toByteArray();
Ray Milkey5c9f2db2014-04-09 10:31:21 -0700269 success &= deserializePropertyMap(SWITCH_KRYO.get(), props);
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700270 this.status = STATUS.values()[sw.getStatus()];
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700271
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700272 return success;
273 } catch (InvalidProtocolBufferException e) {
274 log.error("Deserializing Switch: " + this + " failed.", e);
275 return false;
276 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700277 }
278
279 @Override
280 public String toString() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700281 // TODO output all properties?
282 return "[" + this.getClass().getSimpleName()
283 + " 0x" + Long.toHexString(dpid) + " STATUS:" + status + "]";
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700284 }
285
286}