blob: 6f7b68ca9708ae9f03cca73b6c204f8c4e243576 [file] [log] [blame]
Madan Jampania4be1842016-05-24 15:56:02 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Madan Jampania4be1842016-05-24 15:56:02 -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 */
16package org.onosproject.store.cfg;
17
Thomas Vachuska9f6bd522018-02-12 15:53:01 -080018import com.google.common.collect.ImmutableSet;
Madan Jampania4be1842016-05-24 15:56:02 -070019import org.onosproject.cfg.ComponentConfigEvent;
20import org.onosproject.cfg.ComponentConfigStore;
21import org.onosproject.cfg.ComponentConfigStoreDelegate;
22import org.onosproject.store.AbstractStore;
23import org.onosproject.store.serializers.KryoNamespaces;
24import org.onosproject.store.service.ConsistentMap;
25import org.onosproject.store.service.MapEvent;
26import org.onosproject.store.service.MapEventListener;
27import org.onosproject.store.service.Serializer;
28import org.onosproject.store.service.StorageService;
Thomas Vachuska9f6bd522018-02-12 15:53:01 -080029import org.onosproject.store.service.Versioned;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070030import org.osgi.service.component.annotations.Activate;
31import org.osgi.service.component.annotations.Component;
32import org.osgi.service.component.annotations.Deactivate;
33import org.osgi.service.component.annotations.Reference;
34import org.osgi.service.component.annotations.ReferenceCardinality;
Madan Jampania4be1842016-05-24 15:56:02 -070035import org.slf4j.Logger;
36
Thomas Vachuska9f6bd522018-02-12 15:53:01 -080037import java.util.Objects;
38import java.util.Set;
39
Madan Jampania4be1842016-05-24 15:56:02 -070040import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_SET;
41import static org.onosproject.cfg.ComponentConfigEvent.Type.PROPERTY_UNSET;
42import static org.onosproject.store.service.MapEvent.Type.INSERT;
43import static org.onosproject.store.service.MapEvent.Type.REMOVE;
44import static org.onosproject.store.service.MapEvent.Type.UPDATE;
45import static org.slf4j.LoggerFactory.getLogger;
46
47/**
48 * Manages inventory of component configurations in a distributed data store
49 * that provides strong sequential consistency guarantees.
50 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070051@Component(immediate = true, service = ComponentConfigStore.class)
Madan Jampania4be1842016-05-24 15:56:02 -070052public class DistributedComponentConfigStore
53 extends AbstractStore<ComponentConfigEvent, ComponentConfigStoreDelegate>
54 implements ComponentConfigStore {
55
56 private static final String SEP = "#";
57
58 private final Logger log = getLogger(getClass());
59
60 private ConsistentMap<String, String> properties;
61
Ray Milkeyd84f89b2018-08-17 14:54:17 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampania4be1842016-05-24 15:56:02 -070063 protected StorageService storageService;
64
Thomas Vachuska9f6bd522018-02-12 15:53:01 -080065 private InternalPropertiesListener propertiesListener = new InternalPropertiesListener();
Madan Jampania4be1842016-05-24 15:56:02 -070066
67 @Activate
68 public void activate() {
69 properties = storageService.<String, String>consistentMapBuilder()
70 .withName("onos-component-cfg")
71 .withSerializer(Serializer.using(KryoNamespaces.API))
72 .withRelaxedReadConsistency()
73 .build();
74
75 properties.addListener(propertiesListener);
76 log.info("Started");
77 }
78
79 @Deactivate
80 public void deactivate() {
81 properties.removeListener(propertiesListener);
82 log.info("Stopped");
83 }
84
85 @Override
86 public void setProperty(String componentName, String name, String value) {
87 properties.put(key(componentName, name), value);
88
89 }
90
91 @Override
92 public void unsetProperty(String componentName, String name) {
93 properties.remove(key(componentName, name));
94 }
95
Thomas Vachuska9f6bd522018-02-12 15:53:01 -080096 @Override
97 public Set<String> getProperties(String componentName) {
98 ImmutableSet.Builder<String> names = ImmutableSet.builder();
99 properties.keySet().stream()
100 .filter((String k) -> Objects.equals(componentName, k.substring(0, k.indexOf(SEP))))
101 .map((String k) -> k.substring(k.indexOf(SEP) + 1))
102 .forEach(names::add);
103 return names.build();
104 }
105
106 @Override
107 public String getProperty(String componentName, String name) {
108 Versioned<String> v = properties.get(key(componentName, name));
109 return v != null ? v.value() : null;
110 }
111
Madan Jampania4be1842016-05-24 15:56:02 -0700112 /**
113 * Listener to component configuration properties distributed map changes.
114 */
115 private final class InternalPropertiesListener
116 implements MapEventListener<String, String> {
117
118 @Override
119 public void event(MapEvent<String, String> event) {
120 String[] keys = event.key().split(SEP);
121 if (event.type() == INSERT || event.type() == UPDATE) {
122 String value = event.newValue().value();
Thomas Vachuskad4955ae2016-08-23 14:56:37 -0700123 notifyDelegate(new ComponentConfigEvent(PROPERTY_SET, keys[0], keys[1], value));
Madan Jampania4be1842016-05-24 15:56:02 -0700124 } else if (event.type() == REMOVE) {
Thomas Vachuskad4955ae2016-08-23 14:56:37 -0700125 notifyDelegate(new ComponentConfigEvent(PROPERTY_UNSET, keys[0], keys[1], null));
Madan Jampania4be1842016-05-24 15:56:02 -0700126 }
127 }
128 }
129
130 // Generates a key from component name and property name.
131 private String key(String componentName, String name) {
132 return componentName + SEP + name;
133 }
134}