blob: 20ad5a1162aec74c47e149955caf54e91d314050 [file] [log] [blame]
Madan Jampani5e5b3d62016-02-01 16:03:33 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Madan Jampani5e5b3d62016-02-01 16:03:33 -08003 *
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.primitives.resources.impl;
17
18import java.util.Objects;
19import java.util.Set;
20import java.util.concurrent.CompletableFuture;
21
22import org.onlab.util.Tools;
23import org.onosproject.store.service.AsyncAtomicValue;
24import org.onosproject.store.service.AtomicValueEvent;
25import org.onosproject.store.service.AtomicValueEventListener;
26import org.onosproject.store.service.MapEventListener;
27import org.onosproject.store.service.Versioned;
28
29import com.google.common.collect.Sets;
30
31/**
32 * Implementation of {@link AsyncAtomicValue} backed by {@link AtomixConsistentMap}.
33 */
34public class AtomixValue implements AsyncAtomicValue<String> {
35
36 private final String name;
37 private final AtomixConsistentMap atomixMap;
38 private MapEventListener<String, byte[]> mapEventListener;
39 private final Set<AtomicValueEventListener<String>> listeners = Sets.newIdentityHashSet();
40
41 AtomixValue(String name, AtomixConsistentMap atomixMap) {
42 this.name = name;
43 this.atomixMap = atomixMap;
44 }
45
46 @Override
47 public CompletableFuture<Boolean> compareAndSet(String expect, String update) {
48 return atomixMap.replace(name, Tools.getBytesUtf8(expect), Tools.getBytesUtf8(update));
49 }
50
51 @Override
52 public CompletableFuture<String> get() {
53 return atomixMap.get(name)
54 .thenApply(v -> v != null ? Tools.toStringUtf8(v.value()) : null);
55 }
56
57 @Override
58 public CompletableFuture<String> getAndSet(String value) {
59 return atomixMap.put(name, Tools.getBytesUtf8(value))
60 .thenApply(v -> v != null ? Tools.toStringUtf8(v.value()) : null);
61 }
62
63 @Override
64 public CompletableFuture<Void> set(String value) {
65 return getAndSet(value).thenApply(v -> null);
66 }
67
68 @Override
69 public CompletableFuture<Void> addListener(AtomicValueEventListener<String> listener) {
70 // TODO: synchronization
71 if (mapEventListener == null) {
72 mapEventListener = event -> {
73 Versioned<byte[]> newValue = event.newValue();
74 Versioned<byte[]> oldValue = event.oldValue();
75 if (Objects.equals(event.key(), name)) {
76 listener.event(new AtomicValueEvent<>(name,
77 newValue == null ? null : Tools.toStringUtf8(newValue.value()),
78 oldValue == null ? null : Tools.toStringUtf8(oldValue.value())));
79 }
80 };
81 return atomixMap.addListener(mapEventListener).whenComplete((r, e) -> {
82 if (e == null) {
83 listeners.add(listener);
84 } else {
85 mapEventListener = null;
86 }
87 });
88 } else {
89 listeners.add(listener);
90 return CompletableFuture.completedFuture(null);
91 }
92 }
93
94 @Override
95 public CompletableFuture<Void> removeListener(AtomicValueEventListener<String> listener) {
96 // TODO: synchronization
97 listeners.remove(listener);
98 if (listeners.isEmpty()) {
99 return atomixMap.removeListener(mapEventListener);
100 } else {
101 return CompletableFuture.completedFuture(null);
102 }
103 }
104
105 @Override
106 public String name() {
107 return null;
108 }
109}