blob: 677724df3c87e01a962c191dc6fe057f16b861b2 [file] [log] [blame]
Madan Jampani08706ce2015-04-01 14:49:28 -07001/*
2 * Copyright 2015 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 */
16package org.onosproject.store.consistent.impl;
17
Flavio Castro41b1f3a2015-07-31 13:51:32 -070018import com.google.common.collect.Maps;
19import com.google.common.collect.Sets;
Madan Jampani08706ce2015-04-01 14:49:28 -070020import org.onosproject.store.service.ConsistentMap;
Madan Jampani50589ac2015-06-08 11:38:46 -070021import org.onosproject.store.service.DistributedSet;
22import org.onosproject.store.service.MapEvent;
23import org.onosproject.store.service.MapEventListener;
24import org.onosproject.store.service.SetEvent;
25import org.onosproject.store.service.SetEventListener;
Madan Jampani08706ce2015-04-01 14:49:28 -070026
Flavio Castro41b1f3a2015-07-31 13:51:32 -070027import java.util.Collection;
28import java.util.Iterator;
29import java.util.Map;
30import java.util.Set;
Madan Jampani08706ce2015-04-01 14:49:28 -070031
32/**
33 * Implementation of distributed set that is backed by a ConsistentMap.
34
35 * @param <E> set element type
36 */
Madan Jampani50589ac2015-06-08 11:38:46 -070037public class DefaultDistributedSet<E> implements DistributedSet<E> {
Madan Jampani08706ce2015-04-01 14:49:28 -070038
Flavio Castro41b1f3a2015-07-31 13:51:32 -070039 private static final String CONTAINS = "contains";
40 private static final String PRIMITIVE_NAME = "distributedSet";
41 private static final String SIZE = "size";
42 private static final String IS_EMPTY = "isEmpty";
43 private static final String ITERATOR = "iterator";
44 private static final String TO_ARRAY = "toArray";
45 private static final String ADD = "add";
46 private static final String REMOVE = "remove";
47 private static final String CONTAINS_ALL = "containsAll";
48 private static final String ADD_ALL = "addAll";
49 private static final String RETAIN_ALL = "retainAll";
50 private static final String REMOVE_ALL = "removeAll";
51 private static final String CLEAR = "clear";
52
Madan Jampani50589ac2015-06-08 11:38:46 -070053 private final String name;
Madan Jampani08706ce2015-04-01 14:49:28 -070054 private final ConsistentMap<E, Boolean> backingMap;
Madan Jampani50589ac2015-06-08 11:38:46 -070055 private final Map<SetEventListener<E>, MapEventListener<E, Boolean>> listenerMapping = Maps.newIdentityHashMap();
Flavio Castro41b1f3a2015-07-31 13:51:32 -070056 private final MeteringAgent monitor;
Madan Jampani08706ce2015-04-01 14:49:28 -070057
Flavio Castro41b1f3a2015-07-31 13:51:32 -070058 public DefaultDistributedSet(String name, boolean meteringEnabled, ConsistentMap<E, Boolean> backingMap) {
Madan Jampani50589ac2015-06-08 11:38:46 -070059 this.name = name;
60 this.backingMap = backingMap;
Flavio Castro41b1f3a2015-07-31 13:51:32 -070061 monitor = new MeteringAgent(PRIMITIVE_NAME, name, meteringEnabled);
Madan Jampani08706ce2015-04-01 14:49:28 -070062 }
63
64 @Override
65 public int size() {
Flavio Castro41b1f3a2015-07-31 13:51:32 -070066 final MeteringAgent.Context timer = monitor.startTimer(SIZE);
67 try {
68 return backingMap.size();
69 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -070070 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -070071 }
Madan Jampani08706ce2015-04-01 14:49:28 -070072 }
73
74 @Override
75 public boolean isEmpty() {
Flavio Castro41b1f3a2015-07-31 13:51:32 -070076 final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY);
77 try {
78 return backingMap.isEmpty();
79 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -070080 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -070081 }
Madan Jampani08706ce2015-04-01 14:49:28 -070082 }
83
Madan Jampanibff6d8f2015-03-31 16:53:47 -070084 @SuppressWarnings("unchecked")
Madan Jampani08706ce2015-04-01 14:49:28 -070085 @Override
86 public boolean contains(Object o) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -070087 final MeteringAgent.Context timer = monitor.startTimer(CONTAINS);
88 try {
89 return backingMap.containsKey((E) o);
90 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -070091 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -070092 }
Madan Jampani08706ce2015-04-01 14:49:28 -070093 }
94
95 @Override
96 public Iterator<E> iterator() {
Flavio Castro41b1f3a2015-07-31 13:51:32 -070097 final MeteringAgent.Context timer = monitor.startTimer(ITERATOR);
98 //Do we have to measure this guy?
99 try {
100 return backingMap.keySet().iterator();
101 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700102 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700103 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700104 }
105
106 @Override
107 public Object[] toArray() {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700108 final MeteringAgent.Context timer = monitor.startTimer(TO_ARRAY);
109 try {
110 return backingMap.keySet().stream().toArray();
111 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700112 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700113 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700114 }
115
116 @Override
117 public <T> T[] toArray(T[] a) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700118 final MeteringAgent.Context timer = monitor.startTimer(TO_ARRAY);
119 try {
120 return backingMap.keySet().stream().toArray(size -> a);
121 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700122 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700123 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700124 }
125
126 @Override
127 public boolean add(E e) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700128 final MeteringAgent.Context timer = monitor.startTimer(ADD);
129 try {
130 return backingMap.putIfAbsent(e, true) == null;
131 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700132 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700133 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700134 }
135
Madan Jampanibff6d8f2015-03-31 16:53:47 -0700136 @SuppressWarnings("unchecked")
Madan Jampani08706ce2015-04-01 14:49:28 -0700137 @Override
138 public boolean remove(Object o) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700139 final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
140 try {
141 return backingMap.remove((E) o) != null;
142 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700143 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700144 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700145 }
146
147 @Override
148 public boolean containsAll(Collection<?> c) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700149 final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_ALL);
150 try {
151 return c.stream()
Madan Jampani08706ce2015-04-01 14:49:28 -0700152 .allMatch(this::contains);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700153 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700154 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700155 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700156 }
157
158 @Override
159 public boolean addAll(Collection<? extends E> c) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700160 final MeteringAgent.Context timer = monitor.startTimer(ADD_ALL);
161 try {
162 return c.stream()
Madan Jampani08706ce2015-04-01 14:49:28 -0700163 .map(this::add)
164 .reduce(Boolean::logicalOr)
165 .orElse(false);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700166 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700167 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700168 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700169 }
170
171 @Override
172 public boolean retainAll(Collection<?> c) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700173 final MeteringAgent.Context timer = monitor.startTimer(RETAIN_ALL);
174 try {
175 Set<?> retainSet = Sets.newHashSet(c);
176 return backingMap.keySet()
Madan Jampani08706ce2015-04-01 14:49:28 -0700177 .stream()
178 .filter(k -> !retainSet.contains(k))
179 .map(this::remove)
180 .reduce(Boolean::logicalOr)
181 .orElse(false);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700182 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700183 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700184 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700185 }
186
187 @Override
188 public boolean removeAll(Collection<?> c) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700189 final MeteringAgent.Context timer = monitor.startTimer(REMOVE_ALL);
190 try {
191 Set<?> removeSet = Sets.newHashSet(c);
192 return backingMap.keySet()
193 .stream()
194 .filter(removeSet::contains)
195 .map(this::remove)
196 .reduce(Boolean::logicalOr)
197 .orElse(false);
198 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700199 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700200 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700201 }
202
203 @Override
204 public void clear() {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700205 final MeteringAgent.Context timer = monitor.startTimer(CLEAR);
206 try {
207 backingMap.clear();
208 } finally {
Flavio Castro6e044612015-08-13 14:13:58 -0700209 timer.stop(null);
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700210 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700211 }
Madan Jampani50589ac2015-06-08 11:38:46 -0700212
213 @Override
214 public void addListener(SetEventListener<E> listener) {
215 MapEventListener<E, Boolean> mapEventListener = mapEvent -> {
216 if (mapEvent.type() == MapEvent.Type.INSERT) {
217 listener.event(new SetEvent<>(name, SetEvent.Type.ADD, mapEvent.key()));
218 } else if (mapEvent.type() == MapEvent.Type.REMOVE) {
219 listener.event(new SetEvent<>(name, SetEvent.Type.REMOVE, mapEvent.key()));
220 }
221 };
222 if (listenerMapping.putIfAbsent(listener, mapEventListener) == null) {
223 backingMap.addListener(mapEventListener);
224 }
225 }
226
227 @Override
228 public void removeListener(SetEventListener<E> listener) {
229 MapEventListener<E, Boolean> mapEventListener = listenerMapping.remove(listener);
230 if (mapEventListener != null) {
231 backingMap.removeListener(mapEventListener);
232 }
233 }
Madan Jampani08706ce2015-04-01 14:49:28 -0700234}