blob: 89c8da62db9ed23d47ae83c1246e0973448be7f0 [file] [log] [blame]
Jordan Halterman2bf177c2017-06-29 01:49:08 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jordan Halterman2bf177c2017-06-29 01:49:08 -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 */
16
17package org.onosproject.store.primitives.resources.impl;
18
Jordan Halterman2bf177c2017-06-29 01:49:08 -070019import java.util.HashMap;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070020import java.util.Map;
21import java.util.NavigableMap;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070022import java.util.TreeMap;
Jordan Haltermandae11602018-07-03 00:00:47 -070023import java.util.concurrent.ConcurrentSkipListMap;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070024
Jordan Halterman2bf177c2017-06-29 01:49:08 -070025import com.google.common.collect.Maps;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070026import io.atomix.protocols.raft.service.Commit;
27import io.atomix.protocols.raft.service.RaftServiceExecutor;
28import io.atomix.protocols.raft.session.RaftSession;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070029import org.onlab.util.KryoNamespace;
Jordan Halterman71635ae2017-07-28 10:35:43 -070030import org.onosproject.store.primitives.TransactionId;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070031import org.onosproject.store.serializers.KryoNamespaces;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070032import org.onosproject.store.service.Serializer;
Jordan Halterman71635ae2017-07-28 10:35:43 -070033import org.onosproject.store.service.TransactionLog;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070034import org.onosproject.store.service.Versioned;
35
Jordan Halterman2bf177c2017-06-29 01:49:08 -070036import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CEILING_ENTRY;
37import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CEILING_KEY;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070038import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CeilingEntry;
39import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CeilingKey;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070040import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FIRST_ENTRY;
41import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FIRST_KEY;
42import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FLOOR_ENTRY;
43import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FLOOR_KEY;
44import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FloorEntry;
45import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FloorKey;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070046import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HIGHER_ENTRY;
47import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HIGHER_KEY;
48import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HigherEntry;
49import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HigherKey;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070050import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LAST_ENTRY;
51import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LAST_KEY;
52import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LOWER_ENTRY;
53import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LOWER_KEY;
54import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LowerEntry;
55import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LowerKey;
56import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.POLL_FIRST_ENTRY;
57import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.POLL_LAST_ENTRY;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070058import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.SUB_MAP;
59import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.SubMap;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070060
61/**
62 * State machine corresponding to {@link AtomixConsistentTreeMap} backed by a
63 * {@link TreeMap}.
64 */
Jordan Halterman71635ae2017-07-28 10:35:43 -070065public class AtomixConsistentTreeMapService extends AtomixConsistentMapService {
Jordan Halterman2bf177c2017-06-29 01:49:08 -070066
67 private static final Serializer SERIALIZER = Serializer.using(KryoNamespace.newBuilder()
68 .register(KryoNamespaces.BASIC)
Jordan Halterman71635ae2017-07-28 10:35:43 -070069 .register(AtomixConsistentMapOperations.NAMESPACE)
Jordan Halterman2bf177c2017-06-29 01:49:08 -070070 .register(AtomixConsistentTreeMapOperations.NAMESPACE)
Jordan Halterman71635ae2017-07-28 10:35:43 -070071 .register(AtomixConsistentMapEvents.NAMESPACE)
72 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID + 150)
73 .register(TransactionScope.class)
74 .register(TransactionLog.class)
75 .register(TransactionId.class)
76 .register(MapEntryValue.class)
77 .register(MapEntryValue.Type.class)
78 .register(new HashMap().keySet().getClass())
Jordan Haltermandae11602018-07-03 00:00:47 -070079 .register(ConcurrentSkipListMap.class)
Jordan Halterman2bf177c2017-06-29 01:49:08 -070080 .build());
81
Jordan Halterman2bf177c2017-06-29 01:49:08 -070082 @Override
Jordan Haltermandae11602018-07-03 00:00:47 -070083 protected NavigableMap<String, MapEntryValue> createMap() {
84 return new ConcurrentSkipListMap<>();
Jordan Halterman2bf177c2017-06-29 01:49:08 -070085 }
86
87 @Override
Jordan Haltermandae11602018-07-03 00:00:47 -070088 protected NavigableMap<String, MapEntryValue> entries() {
89 return (NavigableMap<String, MapEntryValue>) super.entries();
Jordan Halterman71635ae2017-07-28 10:35:43 -070090 }
Jordan Halterman2bf177c2017-06-29 01:49:08 -070091
Jordan Halterman71635ae2017-07-28 10:35:43 -070092 @Override
93 protected Serializer serializer() {
94 return SERIALIZER;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070095 }
96
97 @Override
98 public void configure(RaftServiceExecutor executor) {
Jordan Halterman71635ae2017-07-28 10:35:43 -070099 super.configure(executor);
100 executor.register(SUB_MAP, serializer()::decode, this::subMap, serializer()::encode);
101 executor.register(FIRST_KEY, (Commit<Void> c) -> firstKey(), serializer()::encode);
102 executor.register(LAST_KEY, (Commit<Void> c) -> lastKey(), serializer()::encode);
103 executor.register(FIRST_ENTRY, (Commit<Void> c) -> firstEntry(), serializer()::encode);
104 executor.register(LAST_ENTRY, (Commit<Void> c) -> lastEntry(), serializer()::encode);
105 executor.register(POLL_FIRST_ENTRY, (Commit<Void> c) -> pollFirstEntry(), serializer()::encode);
106 executor.register(POLL_LAST_ENTRY, (Commit<Void> c) -> pollLastEntry(), serializer()::encode);
107 executor.register(LOWER_ENTRY, serializer()::decode, this::lowerEntry, serializer()::encode);
108 executor.register(LOWER_KEY, serializer()::decode, this::lowerKey, serializer()::encode);
109 executor.register(FLOOR_ENTRY, serializer()::decode, this::floorEntry, serializer()::encode);
110 executor.register(FLOOR_KEY, serializer()::decode, this::floorKey, serializer()::encode);
111 executor.register(CEILING_ENTRY, serializer()::decode, this::ceilingEntry, serializer()::encode);
112 executor.register(CEILING_KEY, serializer()::decode, this::ceilingKey, serializer()::encode);
113 executor.register(HIGHER_ENTRY, serializer()::decode, this::higherEntry, serializer()::encode);
114 executor.register(HIGHER_KEY, serializer()::decode, this::higherKey, serializer()::encode);
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700115 }
116
Jordan Halterman71635ae2017-07-28 10:35:43 -0700117 protected NavigableMap<String, MapEntryValue> subMap(
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700118 Commit<? extends SubMap> commit) {
119 // Do not support this until lazy communication is possible. At present
120 // it transmits up to the entire map.
Jordan Halterman71635ae2017-07-28 10:35:43 -0700121 SubMap<String, MapEntryValue> subMap = commit.value();
122 return entries().subMap(subMap.fromKey(), subMap.isInclusiveFrom(),
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700123 subMap.toKey(), subMap.isInclusiveTo());
124 }
125
Jordan Halterman71635ae2017-07-28 10:35:43 -0700126 protected String firstKey() {
127 return isEmpty() ? null : entries().firstKey();
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700128 }
129
Jordan Halterman71635ae2017-07-28 10:35:43 -0700130 protected String lastKey() {
131 return isEmpty() ? null : entries().lastKey();
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700132 }
133
134 protected Map.Entry<String, Versioned<byte[]>> higherEntry(Commit<? extends HigherEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700135 return isEmpty() ? null : toVersionedEntry(entries().higherEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700136 }
137
Jordan Halterman71635ae2017-07-28 10:35:43 -0700138 protected Map.Entry<String, Versioned<byte[]>> firstEntry() {
139 return isEmpty() ? null : toVersionedEntry(entries().firstEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700140 }
141
Jordan Halterman71635ae2017-07-28 10:35:43 -0700142 protected Map.Entry<String, Versioned<byte[]>> lastEntry() {
143 return isEmpty() ? null : toVersionedEntry(entries().lastEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700144 }
145
Jordan Halterman71635ae2017-07-28 10:35:43 -0700146 protected Map.Entry<String, Versioned<byte[]>> pollFirstEntry() {
147 return toVersionedEntry(entries().pollFirstEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700148 }
149
Jordan Halterman71635ae2017-07-28 10:35:43 -0700150 protected Map.Entry<String, Versioned<byte[]>> pollLastEntry() {
151 return toVersionedEntry(entries().pollLastEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700152 }
153
154 protected Map.Entry<String, Versioned<byte[]>> lowerEntry(Commit<? extends LowerEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700155 return toVersionedEntry(entries().lowerEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700156 }
157
158 protected String lowerKey(Commit<? extends LowerKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700159 return entries().lowerKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700160 }
161
162 protected Map.Entry<String, Versioned<byte[]>> floorEntry(Commit<? extends FloorEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700163 return toVersionedEntry(entries().floorEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700164 }
165
166 protected String floorKey(Commit<? extends FloorKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700167 return entries().floorKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700168 }
169
170 protected Map.Entry<String, Versioned<byte[]>> ceilingEntry(Commit<CeilingEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700171 return toVersionedEntry(entries().ceilingEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700172 }
173
174 protected String ceilingKey(Commit<CeilingKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700175 return entries().ceilingKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700176 }
177
178 protected String higherKey(Commit<HigherKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700179 return entries().higherKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700180 }
181
182 private Map.Entry<String, Versioned<byte[]>> toVersionedEntry(
Jordan Halterman71635ae2017-07-28 10:35:43 -0700183 Map.Entry<String, MapEntryValue> entry) {
184 return entry == null || valueIsNull(entry.getValue())
185 ? null : Maps.immutableEntry(entry.getKey(), toVersioned(entry.getValue()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700186 }
187
188 @Override
189 public void onExpire(RaftSession session) {
190 closeListener(session.sessionId().id());
191 }
192
193 @Override
194 public void onClose(RaftSession session) {
195 closeListener(session.sessionId().id());
196 }
197
198 private void closeListener(Long sessionId) {
199 listeners.remove(sessionId);
200 }
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700201}