2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.md.sal.dom.broker.impl;
10 import com.google.common.base.Preconditions;
11 import java.util.Collection;
12 import java.util.EnumMap;
13 import java.util.HashMap;
15 import java.util.Map.Entry;
16 import java.util.TreeMap;
17 import javax.annotation.concurrent.GuardedBy;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
20 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeListener;
21 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeProducer;
22 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeService;
23 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShard;
24 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShardingConflictException;
25 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeShardingService;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * Shared DOM data tree.
33 * @deprecated Use {@link org.opendaylight.mdsal.dom.broker.ShardedDOMDataTree} instead.
36 public final class ShardedDOMDataTree implements DOMDataTreeService, DOMDataTreeShardingService {
37 private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMDataTree.class);
38 private final Map<LogicalDatastoreType, ShardingTableEntry> shardingTables = new EnumMap<>(
39 LogicalDatastoreType.class);
41 private final Map<DOMDataTreeIdentifier, DOMDataTreeProducer> idToProducer = new TreeMap<>();
44 private ShardingTableEntry lookupShard(final DOMDataTreeIdentifier prefix) {
45 final ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
50 return t.lookup(prefix.getRootIdentifier());
54 private void storeShard(final DOMDataTreeIdentifier prefix, final ShardRegistration<?> reg) {
55 ShardingTableEntry shardingTableEntry = shardingTables
56 .computeIfAbsent(prefix.getDatastoreType(), k -> new ShardingTableEntry());
58 shardingTableEntry.store(prefix.getRootIdentifier(), reg);
61 void removeShard(final ShardRegistration<?> reg) {
62 final DOMDataTreeIdentifier prefix = reg.getPrefix();
63 final ShardRegistration<?> parentReg;
66 final ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
68 LOG.warn("Shard registration {} points to non-existent table", reg);
72 t.remove(prefix.getRootIdentifier());
73 parentReg = lookupShard(prefix).getRegistration();
76 * FIXME: adjust all producers. This is tricky, as we need different locking strategy,
77 * simply because we risk AB/BA deadlock with a producer being split off from
83 if (parentReg != null) {
84 parentReg.getInstance().onChildDetached(prefix, reg.getInstance());
89 public <T extends DOMDataTreeShard> ListenerRegistration<T> registerDataTreeShard(
90 final DOMDataTreeIdentifier prefix, final T shard) throws DOMDataTreeShardingConflictException {
91 final ShardRegistration<T> reg;
92 final ShardRegistration<?> parentReg;
96 * Lookup the parent shard (e.g. the one which currently matches the prefix),
97 * and if it exists, check if its registration prefix does not collide with
100 final ShardingTableEntry parent = lookupShard(prefix);
101 parentReg = parent.getRegistration();
102 if (parentReg != null && prefix.equals(parentReg.getPrefix())) {
103 throw new DOMDataTreeShardingConflictException(
104 String.format("Prefix %s is already occupied by shard %s", prefix, parentReg.getInstance()));
107 // FIXME: wrap the shard in a proper adaptor based on implemented interface
109 reg = new ShardRegistration<>(this, prefix, shard);
111 storeShard(prefix, reg);
113 // FIXME: update any producers/registrations
116 // Notify the parent shard
117 if (parentReg != null) {
118 parentReg.getInstance().onChildAttached(prefix, shard);
125 private DOMDataTreeProducer findProducer(final DOMDataTreeIdentifier subtree) {
126 for (final Entry<DOMDataTreeIdentifier, DOMDataTreeProducer> e : idToProducer.entrySet()) {
127 if (e.getKey().contains(subtree)) {
135 synchronized void destroyProducer(final ShardedDOMDataTreeProducer producer) {
136 for (final DOMDataTreeIdentifier s : producer.getSubtrees()) {
137 final DOMDataTreeProducer r = idToProducer.remove(s);
138 if (!producer.equals(r)) {
139 LOG.error("Removed producer {} on subtree {} while removing {}", r, s, producer);
145 private DOMDataTreeProducer createProducer(final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap) {
146 // Record the producer's attachment points
147 final DOMDataTreeProducer ret = ShardedDOMDataTreeProducer.create(this, shardMap);
148 for (DOMDataTreeIdentifier s : shardMap.keySet()) {
149 idToProducer.put(s, ret);
156 public synchronized DOMDataTreeProducer createProducer(final Collection<DOMDataTreeIdentifier> subtrees) {
157 Preconditions.checkArgument(!subtrees.isEmpty(), "Subtrees may not be empty");
159 final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap = new HashMap<>();
160 for (final DOMDataTreeIdentifier s : subtrees) {
161 // Attempting to create a disconnected producer -- all subtrees have to be unclaimed
162 final DOMDataTreeProducer producer = findProducer(s);
163 Preconditions.checkArgument(producer == null, "Subtree %s is attached to producer %s", s, producer);
165 shardMap.put(s, lookupShard(s).getRegistration().getInstance());
168 return createProducer(shardMap);
171 synchronized DOMDataTreeProducer createProducer(final ShardedDOMDataTreeProducer parent,
172 final Collection<DOMDataTreeIdentifier> subtrees) {
173 Preconditions.checkNotNull(parent);
175 final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap = new HashMap<>();
176 for (final DOMDataTreeIdentifier s : subtrees) {
177 shardMap.put(s, lookupShard(s).getRegistration().getInstance());
180 return createProducer(shardMap);
184 public synchronized <T extends DOMDataTreeListener> ListenerRegistration<T>
185 registerListener(final T listener,
186 final Collection<DOMDataTreeIdentifier> subtrees,
187 final boolean allowRxMerges,
188 final Collection<DOMDataTreeProducer> producers) {
189 // FIXME Implement this.
190 throw new UnsupportedOperationException("Not implemented yet.");