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.mdsal.dom.broker;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.ArrayListMultimap;
14 import com.google.common.collect.BiMap;
15 import com.google.common.collect.ImmutableBiMap;
16 import com.google.common.collect.ImmutableBiMap.Builder;
17 import com.google.common.collect.ImmutableMap;
18 import com.google.common.collect.Maps;
19 import com.google.common.collect.Multimap;
20 import java.util.ArrayList;
21 import java.util.Collection;
23 import java.util.Map.Entry;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducer;
27 import org.opendaylight.mdsal.dom.api.DOMDataTreeShard;
28 import org.opendaylight.mdsal.dom.spi.shard.DOMDataTreeShardProducer;
29 import org.opendaylight.mdsal.dom.spi.shard.DOMDataTreeShardWriteTransaction;
30 import org.opendaylight.mdsal.dom.spi.shard.WriteableDOMDataTreeShard;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 final class ProducerLayout {
37 private static final Logger LOG = LoggerFactory.getLogger(ProducerLayout.class);
39 private final BiMap<DOMDataTreeIdentifier, DOMDataTreeShardProducer> idToProducer;
40 private final Map<DOMDataTreeIdentifier, DOMDataTreeProducer> children;
41 private final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap;
43 private ProducerLayout(final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap,
44 final BiMap<DOMDataTreeIdentifier, DOMDataTreeShardProducer> idToProducer,
45 final Map<DOMDataTreeIdentifier, DOMDataTreeProducer> children) {
46 this.shardMap = ImmutableMap.copyOf(shardMap);
47 this.idToProducer = requireNonNull(idToProducer);
48 this.children = requireNonNull(children);
51 static ProducerLayout create(final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap) {
52 return new ProducerLayout(shardMap, mapIdsToProducer(shardMap), ImmutableMap.of());
55 private static BiMap<DOMDataTreeIdentifier, DOMDataTreeShardProducer> mapIdsToProducer(
56 final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap) {
57 final Multimap<DOMDataTreeShard, DOMDataTreeIdentifier> shardToId = ArrayListMultimap.create();
58 // map which identifier belongs to which shard
59 for (final Entry<DOMDataTreeIdentifier, DOMDataTreeShard> entry : shardMap.entrySet()) {
60 shardToId.put(entry.getValue(), entry.getKey());
63 final Builder<DOMDataTreeIdentifier, DOMDataTreeShardProducer> idToProducerBuilder = ImmutableBiMap.builder();
64 for (final Entry<DOMDataTreeShard, Collection<DOMDataTreeIdentifier>> entry : shardToId.asMap().entrySet()) {
65 if (entry.getKey() instanceof WriteableDOMDataTreeShard) {
66 //create a single producer for all prefixes in a single shard
67 final DOMDataTreeShardProducer producer = ((WriteableDOMDataTreeShard) entry.getKey())
68 .createProducer(entry.getValue());
69 // id mapped to producers
70 for (final DOMDataTreeIdentifier id : entry.getValue()) {
71 idToProducerBuilder.put(id, producer);
74 LOG.error("Unable to create a producer for shard that's not a WriteableDOMDataTreeShard");
78 return idToProducerBuilder.build();
81 ProducerLayout addChild(final DOMDataTreeProducer producer, final Collection<DOMDataTreeIdentifier> subtrees) {
82 final ImmutableMap.Builder<DOMDataTreeIdentifier, DOMDataTreeProducer> cb = ImmutableMap.builder();
84 for (final DOMDataTreeIdentifier s : subtrees) {
88 return new ProducerLayout(shardMap, idToProducer, cb.build());
91 ProducerLayout reshard(final Map<DOMDataTreeIdentifier, DOMDataTreeShard> newShardMap) {
93 return new ProducerLayout(newShardMap, mapIdsToProducer(newShardMap), children);
96 boolean haveSubtree(final DOMDataTreeIdentifier subtree) {
97 for (final DOMDataTreeIdentifier i : shardMap.keySet()) {
98 if (i.contains(subtree)) {
106 DOMDataTreeProducer lookupChild(final DOMDataTreeIdentifier path) {
107 for (final Entry<DOMDataTreeIdentifier, DOMDataTreeProducer> e : children.entrySet()) {
108 if (e.getKey().contains(path)) {
109 // FIXME: does this match wildcards?
117 Set<DOMDataTreeIdentifier> getChildTrees() {
118 return children.keySet();
121 void checkAvailable(final Collection<PathArgument> base, final PathArgument child) {
122 if (!children.isEmpty()) {
123 final Collection<PathArgument> args = new ArrayList<>(base.size() + 1);
127 final YangInstanceIdentifier path = YangInstanceIdentifier.create(args);
128 for (final DOMDataTreeIdentifier c : children.keySet()) {
129 Preconditions.checkArgument(!c.getRootIdentifier().contains(path),
130 "Path {%s} is not available to this cursor since it's already claimed by a child producer", path);
135 Map<DOMDataTreeIdentifier, DOMDataTreeShardWriteTransaction> createTransactions() {
136 Preconditions.checkState(!idToProducer.isEmpty(),
137 "Cannot create transaction since the producer is not mapped to any shard");
138 return Maps.transformValues(idToProducer, DOMDataTreeShardProducer::createTransaction);
142 idToProducer.values().forEach(DOMDataTreeShardProducer::close);