import com.google.common.base.Preconditions;
import java.util.Collection;
-import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.annotation.concurrent.GuardedBy;
-import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMDataTreeListener;
import org.opendaylight.mdsal.dom.api.DOMDataTreeLoopException;
public final class ShardedDOMDataTree implements DOMDataTreeService, DOMDataTreeShardingService {
private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMDataTree.class);
- private final Map<LogicalDatastoreType, ShardingTableEntry> shardingTables = new EnumMap<>(LogicalDatastoreType.class);
- @GuardedBy("this")
- private final Map<DOMDataTreeIdentifier, DOMDataTreeProducer> idToProducer = new TreeMap<>();
@GuardedBy("this")
- private ShardingTableEntry lookupShard(final DOMDataTreeIdentifier prefix) {
- final ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
- if (t == null) {
- return null;
- }
-
- return t.lookup(prefix.getRootIdentifier());
- }
-
+ private final ShardingTable<ShardRegistration<?>> shards = ShardingTable.create();
@GuardedBy("this")
- private void storeShard(final DOMDataTreeIdentifier prefix, final ShardRegistration<?> reg) {
- ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
- if (t == null) {
- t = new ShardingTableEntry();
- shardingTables.put(prefix.getDatastoreType(), t);
- }
+ private final Map<DOMDataTreeIdentifier, DOMDataTreeProducer> idToProducer = new TreeMap<>();
- t.store(prefix.getRootIdentifier(), reg);
- }
void removeShard(final ShardRegistration<?> reg) {
final DOMDataTreeIdentifier prefix = reg.getPrefix();
final ShardRegistration<?> parentReg;
synchronized (this) {
- final ShardingTableEntry t = shardingTables.get(prefix.getDatastoreType());
- if (t == null) {
- LOG.warn("Shard registration {} points to non-existent table", reg);
- return;
- }
-
- t.remove(prefix.getRootIdentifier());
- parentReg = lookupShard(prefix).getRegistration();
+ shards.remove(prefix);
+ parentReg = shards.lookup(prefix).getValue();
/*
* FIXME: adjust all producers and listeners. This is tricky, as we need different
* and if it exists, check if its registration prefix does not collide with
* this registration.
*/
- final ShardingTableEntry parent = lookupShard(prefix);
+ final ShardingTableEntry<ShardRegistration<?>> parent = shards.lookup(prefix);
if (parent != null) {
- parentReg = parent.getRegistration();
+ parentReg = parent.getValue();
if (parentReg != null && prefix.equals(parentReg.getPrefix())) {
throw new DOMDataTreeShardingConflictException(String.format(
"Prefix %s is already occupied by shard %s", prefix, parentReg.getInstance()));
reg = new ShardRegistration<T>(this, prefix, shard);
- storeShard(prefix, reg);
+ shards.store(prefix, reg);
// FIXME: update any producers/registrations
}
final DOMDataTreeProducer producer = findProducer(s);
Preconditions.checkArgument(producer == null, "Subtree %s is attached to producer %s", s, producer);
- shardMap.put(s, lookupShard(s).getRegistration().getInstance());
+ shardMap.put(s, shards.lookup(s).getValue().getInstance());
}
return createProducer(shardMap);
final Map<DOMDataTreeIdentifier, DOMDataTreeShard> shardMap = new HashMap<>();
for (final DOMDataTreeIdentifier s : subtrees) {
- shardMap.put(s, lookupShard(s).getRegistration().getInstance());
+ shardMap.put(s, shards.lookup(s).getValue().getInstance());
}
return createProducer(shardMap);
}
for (DOMDataTreeIdentifier subtree : subtrees) {
- DOMDataTreeShard shard = lookupShard(subtree).getRegistration().getInstance();
+ DOMDataTreeShard shard = shards.lookup(subtree).getValue().getInstance();
// FIXME: What should we do if listener is wildcard? And shards are on per
// node basis?
Preconditions.checkArgument(shard instanceof DOMStoreTreeChangePublisher,
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.dom.broker;
+
+import java.util.EnumMap;
+import java.util.Map;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class ShardingTable<V> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ShardingTable.class);
+ private final Map<LogicalDatastoreType, ShardingTableEntry<V>> roots = new EnumMap<>(LogicalDatastoreType.class);
+
+ private ShardingTable() {
+
+ }
+
+ static <V> ShardingTable<V> create() {
+ return new ShardingTable<>();
+ }
+
+ ShardingTableEntry<V> lookup(final DOMDataTreeIdentifier prefix) {
+ final ShardingTableEntry<V> t = roots.get(prefix.getDatastoreType());
+ if (t == null) {
+ return null;
+ }
+
+ return t.lookup(prefix.getRootIdentifier());
+ }
+
+ void store(final DOMDataTreeIdentifier prefix, final V reg) {
+ ShardingTableEntry<V> t = roots.get(prefix.getDatastoreType());
+ if (t == null) {
+ t = new ShardingTableEntry<V>();
+ roots.put(prefix.getDatastoreType(), t);
+ }
+
+ t.store(prefix.getRootIdentifier(), reg);
+ }
+
+ void remove(final DOMDataTreeIdentifier prefix) {
+ final ShardingTableEntry<V> t = roots.get(prefix.getDatastoreType());
+ if (t == null) {
+ LOG.warn("Shard registration {} points to non-existent table", t);
+ return;
+ }
+
+ t.remove(prefix.getRootIdentifier());
+ }
+
+}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class ShardingTableEntry implements Identifiable<PathArgument> {
+final class ShardingTableEntry<V> implements Identifiable<PathArgument> {
private static final Logger LOG = LoggerFactory.getLogger(ShardingTableEntry.class);
// FIXME: We do probably want to adapt map
- private final Map<PathArgument, ShardingTableEntry> children = new HashMap<>();
+ private final Map<PathArgument, ShardingTableEntry<V>> children = new HashMap<>();
private final PathArgument identifier;
- private ShardRegistration<?> registration;
+ private V value;
ShardingTableEntry() {
identifier = null;
return identifier;
}
- public ShardRegistration<?> getRegistration() {
- return registration;
+ public V getValue() {
+ return value;
}
- ShardingTableEntry lookup(final YangInstanceIdentifier id) {
+ ShardingTableEntry<V> lookup(final YangInstanceIdentifier id) {
final Iterator<PathArgument> it = id.getPathArguments().iterator();
- ShardingTableEntry entry = this;
+ ShardingTableEntry<V> entry = this;
while (it.hasNext()) {
final PathArgument a = it.next();
- final ShardingTableEntry child = entry.children.get(a);
+ final ShardingTableEntry<V> child = entry.children.get(a);
if (child == null) {
LOG.debug("Lookup of {} stopped at {}", id, a);
break;
return entry;
}
- void store(final YangInstanceIdentifier id, final ShardRegistration<?> reg) {
+ void store(final YangInstanceIdentifier id, final V reg) {
final Iterator<PathArgument> it = id.getPathArguments().iterator();
- ShardingTableEntry entry = this;
+ ShardingTableEntry<V> entry = this;
while (it.hasNext()) {
final PathArgument a = it.next();
- ShardingTableEntry child = entry.children.get(a);
+ ShardingTableEntry<V> child = entry.children.get(a);
if (child == null) {
- child = new ShardingTableEntry(a);
+ child = new ShardingTableEntry<>(a);
entry.children.put(a, child);
}
// TODO: Is this correct? We want to enter child
entry = child;
}
- Preconditions.checkState(entry.registration == null);
- entry.registration = reg;
+ Preconditions.checkState(entry.value == null);
+ entry.value = reg;
}
private boolean remove(final Iterator<PathArgument> it) {
if (it.hasNext()) {
final PathArgument arg = it.next();
- final ShardingTableEntry child = children.get(arg);
+ final ShardingTableEntry<V> child = children.get(arg);
if (child != null) {
if (child.remove(it)) {
children.remove(arg);
}
} else {
/*
- * Iterator is empty, this effectivelly means is table entry to remove registration.
- * FIXME: We probably want to compare registration object to make sure we are removing
- * correct shard.
+ * Iterator is empty, this effectively means is table entry to remove registration.
+ * FIXME: We probably want to compare value to make sure we are removing correct value.
*/
- registration = null;
+ value = null;
}
- return registration == null && children.isEmpty();
+ return value == null && children.isEmpty();
}
void remove(final YangInstanceIdentifier id) {