blob: f0890514ceea2a9c6b2e5b5025e32fa1c82cd9d7 [file] [log] [blame]
Jordan Halterman2bf177c2017-06-29 01:49:08 -07001/*
2 * Copyright 2016-present 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 */
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 Halterman2bf177c2017-06-29 01:49:08 -070023
Jordan Halterman2bf177c2017-06-29 01:49:08 -070024import com.google.common.collect.Maps;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070025import io.atomix.protocols.raft.service.Commit;
26import io.atomix.protocols.raft.service.RaftServiceExecutor;
27import io.atomix.protocols.raft.session.RaftSession;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070028import org.onlab.util.KryoNamespace;
Jordan Halterman71635ae2017-07-28 10:35:43 -070029import org.onosproject.store.primitives.TransactionId;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070030import org.onosproject.store.serializers.KryoNamespaces;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070031import org.onosproject.store.service.Serializer;
Jordan Halterman71635ae2017-07-28 10:35:43 -070032import org.onosproject.store.service.TransactionLog;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070033import org.onosproject.store.service.Versioned;
34
Jordan Halterman2bf177c2017-06-29 01:49:08 -070035import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CEILING_ENTRY;
36import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CEILING_KEY;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070037import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CeilingEntry;
38import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.CeilingKey;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070039import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FIRST_ENTRY;
40import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FIRST_KEY;
41import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FLOOR_ENTRY;
42import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FLOOR_KEY;
43import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FloorEntry;
44import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.FloorKey;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070045import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HIGHER_ENTRY;
46import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HIGHER_KEY;
47import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HigherEntry;
48import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.HigherKey;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070049import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LAST_ENTRY;
50import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LAST_KEY;
51import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LOWER_ENTRY;
52import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LOWER_KEY;
53import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LowerEntry;
54import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.LowerKey;
55import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.POLL_FIRST_ENTRY;
56import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.POLL_LAST_ENTRY;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070057import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.SUB_MAP;
58import static org.onosproject.store.primitives.resources.impl.AtomixConsistentTreeMapOperations.SubMap;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070059
60/**
61 * State machine corresponding to {@link AtomixConsistentTreeMap} backed by a
62 * {@link TreeMap}.
63 */
Jordan Halterman71635ae2017-07-28 10:35:43 -070064public class AtomixConsistentTreeMapService extends AtomixConsistentMapService {
Jordan Halterman2bf177c2017-06-29 01:49:08 -070065
66 private static final Serializer SERIALIZER = Serializer.using(KryoNamespace.newBuilder()
67 .register(KryoNamespaces.BASIC)
Jordan Halterman71635ae2017-07-28 10:35:43 -070068 .register(AtomixConsistentMapOperations.NAMESPACE)
Jordan Halterman2bf177c2017-06-29 01:49:08 -070069 .register(AtomixConsistentTreeMapOperations.NAMESPACE)
Jordan Halterman71635ae2017-07-28 10:35:43 -070070 .register(AtomixConsistentMapEvents.NAMESPACE)
71 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID + 150)
72 .register(TransactionScope.class)
73 .register(TransactionLog.class)
74 .register(TransactionId.class)
75 .register(MapEntryValue.class)
76 .register(MapEntryValue.Type.class)
77 .register(new HashMap().keySet().getClass())
Jordan Halterman2bf177c2017-06-29 01:49:08 -070078 .register(TreeMap.class)
79 .build());
80
Jordan Halterman2bf177c2017-06-29 01:49:08 -070081 @Override
Jordan Halterman71635ae2017-07-28 10:35:43 -070082 protected TreeMap<String, MapEntryValue> createMap() {
83 return Maps.newTreeMap();
Jordan Halterman2bf177c2017-06-29 01:49:08 -070084 }
85
86 @Override
Jordan Halterman71635ae2017-07-28 10:35:43 -070087 protected TreeMap<String, MapEntryValue> entries() {
88 return (TreeMap<String, MapEntryValue>) super.entries();
89 }
Jordan Halterman2bf177c2017-06-29 01:49:08 -070090
Jordan Halterman71635ae2017-07-28 10:35:43 -070091 @Override
92 protected Serializer serializer() {
93 return SERIALIZER;
Jordan Halterman2bf177c2017-06-29 01:49:08 -070094 }
95
96 @Override
97 public void configure(RaftServiceExecutor executor) {
Jordan Halterman71635ae2017-07-28 10:35:43 -070098 super.configure(executor);
99 executor.register(SUB_MAP, serializer()::decode, this::subMap, serializer()::encode);
100 executor.register(FIRST_KEY, (Commit<Void> c) -> firstKey(), serializer()::encode);
101 executor.register(LAST_KEY, (Commit<Void> c) -> lastKey(), serializer()::encode);
102 executor.register(FIRST_ENTRY, (Commit<Void> c) -> firstEntry(), serializer()::encode);
103 executor.register(LAST_ENTRY, (Commit<Void> c) -> lastEntry(), serializer()::encode);
104 executor.register(POLL_FIRST_ENTRY, (Commit<Void> c) -> pollFirstEntry(), serializer()::encode);
105 executor.register(POLL_LAST_ENTRY, (Commit<Void> c) -> pollLastEntry(), serializer()::encode);
106 executor.register(LOWER_ENTRY, serializer()::decode, this::lowerEntry, serializer()::encode);
107 executor.register(LOWER_KEY, serializer()::decode, this::lowerKey, serializer()::encode);
108 executor.register(FLOOR_ENTRY, serializer()::decode, this::floorEntry, serializer()::encode);
109 executor.register(FLOOR_KEY, serializer()::decode, this::floorKey, serializer()::encode);
110 executor.register(CEILING_ENTRY, serializer()::decode, this::ceilingEntry, serializer()::encode);
111 executor.register(CEILING_KEY, serializer()::decode, this::ceilingKey, serializer()::encode);
112 executor.register(HIGHER_ENTRY, serializer()::decode, this::higherEntry, serializer()::encode);
113 executor.register(HIGHER_KEY, serializer()::decode, this::higherKey, serializer()::encode);
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700114 }
115
Jordan Halterman71635ae2017-07-28 10:35:43 -0700116 protected NavigableMap<String, MapEntryValue> subMap(
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700117 Commit<? extends SubMap> commit) {
118 // Do not support this until lazy communication is possible. At present
119 // it transmits up to the entire map.
Jordan Halterman71635ae2017-07-28 10:35:43 -0700120 SubMap<String, MapEntryValue> subMap = commit.value();
121 return entries().subMap(subMap.fromKey(), subMap.isInclusiveFrom(),
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700122 subMap.toKey(), subMap.isInclusiveTo());
123 }
124
Jordan Halterman71635ae2017-07-28 10:35:43 -0700125 protected String firstKey() {
126 return isEmpty() ? null : entries().firstKey();
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700127 }
128
Jordan Halterman71635ae2017-07-28 10:35:43 -0700129 protected String lastKey() {
130 return isEmpty() ? null : entries().lastKey();
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700131 }
132
133 protected Map.Entry<String, Versioned<byte[]>> higherEntry(Commit<? extends HigherEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700134 return isEmpty() ? null : toVersionedEntry(entries().higherEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700135 }
136
Jordan Halterman71635ae2017-07-28 10:35:43 -0700137 protected Map.Entry<String, Versioned<byte[]>> firstEntry() {
138 return isEmpty() ? null : toVersionedEntry(entries().firstEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700139 }
140
Jordan Halterman71635ae2017-07-28 10:35:43 -0700141 protected Map.Entry<String, Versioned<byte[]>> lastEntry() {
142 return isEmpty() ? null : toVersionedEntry(entries().lastEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700143 }
144
Jordan Halterman71635ae2017-07-28 10:35:43 -0700145 protected Map.Entry<String, Versioned<byte[]>> pollFirstEntry() {
146 return toVersionedEntry(entries().pollFirstEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700147 }
148
Jordan Halterman71635ae2017-07-28 10:35:43 -0700149 protected Map.Entry<String, Versioned<byte[]>> pollLastEntry() {
150 return toVersionedEntry(entries().pollLastEntry());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700151 }
152
153 protected Map.Entry<String, Versioned<byte[]>> lowerEntry(Commit<? extends LowerEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700154 return toVersionedEntry(entries().lowerEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700155 }
156
157 protected String lowerKey(Commit<? extends LowerKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700158 return entries().lowerKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700159 }
160
161 protected Map.Entry<String, Versioned<byte[]>> floorEntry(Commit<? extends FloorEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700162 return toVersionedEntry(entries().floorEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700163 }
164
165 protected String floorKey(Commit<? extends FloorKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700166 return entries().floorKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700167 }
168
169 protected Map.Entry<String, Versioned<byte[]>> ceilingEntry(Commit<CeilingEntry> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700170 return toVersionedEntry(entries().ceilingEntry(commit.value().key()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700171 }
172
173 protected String ceilingKey(Commit<CeilingKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700174 return entries().ceilingKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700175 }
176
177 protected String higherKey(Commit<HigherKey> commit) {
Jordan Halterman71635ae2017-07-28 10:35:43 -0700178 return entries().higherKey(commit.value().key());
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700179 }
180
181 private Map.Entry<String, Versioned<byte[]>> toVersionedEntry(
Jordan Halterman71635ae2017-07-28 10:35:43 -0700182 Map.Entry<String, MapEntryValue> entry) {
183 return entry == null || valueIsNull(entry.getValue())
184 ? null : Maps.immutableEntry(entry.getKey(), toVersioned(entry.getValue()));
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700185 }
186
187 @Override
188 public void onExpire(RaftSession session) {
189 closeListener(session.sessionId().id());
190 }
191
192 @Override
193 public void onClose(RaftSession session) {
194 closeListener(session.sessionId().id());
195 }
196
197 private void closeListener(Long sessionId) {
198 listeners.remove(sessionId);
199 }
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700200}