blob: 9f865e02410c51c04092f46e875a11eca6de5343 [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;
10import net.onrc.onos.core.datastore.RCProtos.SwitchProperty;
11import 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
31 private static final ThreadLocal<Kryo> switchKryo = 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
46 public static final String GLOBAL_SWITCH_TABLE_NAME = "G:Switch";
47
48 // must not re-order enum members, ordinal will be sent over wire
49 public enum STATUS {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070050 INACTIVE, ACTIVE;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070051 }
52
53 private final Long dpid;
54 private STATUS status;
55
56 public static byte[] getSwitchID(final Long dpid) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070057 return SwitchEvent.getSwitchID(dpid).array();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070058 }
59
60 public static long getDpidFromKey(final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070061 return getDpidFromKey(ByteBuffer.wrap(key));
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070062 }
63
64 public static long getDpidFromKey(final ByteBuffer keyBuf) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070065 if (keyBuf.getChar() != 'S') {
66 throw new IllegalArgumentException("Invalid Switch key");
67 }
68 return keyBuf.getLong();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070069 }
70
71 // FIXME specify DPID here, or Should caller specify the key it self?
72 // In other words, should layer above have the control of the ID?
73 public KVSwitch(final Long dpid) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070074 super(DataStoreClient.getClient().getTable(GLOBAL_SWITCH_TABLE_NAME), getSwitchID(dpid));
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070075
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070076 this.dpid = dpid;
77 this.status = STATUS.INACTIVE;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070078 }
79
80 /**
81 * Get an instance from Key.
82 *
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070083 * @param key
84 * @return KVSwitch instance
Ray Milkey269ffb92014-04-03 14:43:30 -070085 * @note You need to call `read()` to get the DB content.
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070086 */
87 public static KVSwitch createFromKey(final byte[] key) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070088 return new KVSwitch(getDpidFromKey(key));
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070089 }
90
91 public static Iterable<KVSwitch> getAllSwitches() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070092 return new SwitchEnumerator();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -070093 }
94
95 public static class SwitchEnumerator implements Iterable<KVSwitch> {
96
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -070097 @Override
98 public Iterator<KVSwitch> iterator() {
99 return new SwitchIterator();
100 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700101 }
102
103 public static class SwitchIterator extends AbstractObjectIterator<KVSwitch> {
104
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700105 public SwitchIterator() {
106 super(DataStoreClient.getClient().getTable(GLOBAL_SWITCH_TABLE_NAME));
107 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700108
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700109 @Override
110 public KVSwitch next() {
111 IKVEntry o = enumerator.next();
112 KVSwitch e = KVSwitch.createFromKey(o.getKey());
113 e.deserialize(o.getValue(), o.getVersion());
114 return e;
115 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700116 }
117
118 public STATUS getStatus() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700119 return status;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700120 }
121
122 public void setStatus(final STATUS status) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700123 this.status = status;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700124 }
125
126 public Long getDpid() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700127 return dpid;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700128 }
129
130 public byte[] getId() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700131 return getKey();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700132 }
133
134 @Override
135 public byte[] serialize() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700136 Map<Object, Object> map = getPropertyMap();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700137
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700138 SwitchProperty.Builder sw = SwitchProperty.newBuilder();
139 sw.setDpid(dpid);
140 sw.setStatus(status.ordinal());
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700141
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700142 if (!map.isEmpty()) {
143 byte[] propMaps = serializePropertyMap(switchKryo.get(), map);
144 sw.setValue(ByteString.copyFrom(propMaps));
145 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700146
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700147 return sw.build().toByteArray();
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700148 }
149
150 @Override
151 protected boolean deserialize(final byte[] bytes) {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700152 try {
153 boolean success = true;
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700154
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700155 SwitchProperty sw = SwitchProperty.parseFrom(bytes);
156 byte[] props = sw.getValue().toByteArray();
157 success &= deserializePropertyMap(switchKryo.get(), props);
158 this.status = STATUS.values()[sw.getStatus()];
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700159
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700160 return success;
161 } catch (InvalidProtocolBufferException e) {
162 log.error("Deserializing Switch: " + this + " failed.", e);
163 return false;
164 }
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700165 }
166
167 @Override
168 public String toString() {
Yuta HIGUCHI826b4a42014-03-24 13:10:33 -0700169 // TODO output all properties?
170 return "[" + this.getClass().getSimpleName()
171 + " 0x" + Long.toHexString(dpid) + " STATUS:" + status + "]";
Yuta HIGUCHI66ca1bf2014-03-12 18:34:09 -0700172 }
173
174}