From: Madhu Venugopal
Date: Sat, 2 Aug 2014 07:33:30 +0000 (+0000)
Subject: Merge "Added hosttracker shell for karaf (rebased)"
X-Git-Tag: release/helium~364
X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=5ffd4b46ca00fc8f3d801050670c890117dc0811;hp=a22e44963c31452b6ea17745b652456b8b991101
Merge "Added hosttracker shell for karaf (rebased)"
---
diff --git a/.gitignore b/.gitignore
index f8cf74f826..9144cda4cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,5 @@ out/
maven-eclipse.xml
.DS_STORE
.metadata
+opendaylight/md-sal/sal-distributed-datastore/journal
+
diff --git a/features/config-netty/src/main/resources/features.xml b/features/config-netty/src/main/resources/features.xml
index 3121ca01a2..f1b2d1f753 100644
--- a/features/config-netty/src/main/resources/features.xml
+++ b/features/config-netty/src/main/resources/features.xml
@@ -12,5 +12,6 @@
mvn:org.opendaylight.controller/threadpool-config-api/${project.version}mvn:org.opendaylight.controller/threadpool-config-impl/${project.version}odl-config-startup
+ mvn:org.opendaylight.controller/config-netty-config/${config.version}/xml/config
\ No newline at end of file
diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml
index c21ed78064..dd7d7dfbb9 100644
--- a/opendaylight/commons/opendaylight/pom.xml
+++ b/opendaylight/commons/opendaylight/pom.xml
@@ -1241,6 +1241,26 @@
sal-rest-connector-config${mdsal.version}
+
+ org.opendaylight.controller
+ config-netty-config
+ ${config.version}
+
+
+ org.opendaylight.controller
+ md-sal-config
+ ${mdsal.version}
+
+
+ org.opendaylight.controller
+ netconf-config
+ ${netconf.version}
+
+
+ org.opendaylight.controller
+ netconf-connector-config
+ ${netconf.version}
+ org.opendaylight.controllersal-rest-docgen
@@ -1497,6 +1517,11 @@
sample-toaster-provider${mdsal.version}
+
+ org.opendaylight.controller.samples
+ toaster-config
+ ${mdsal.version}
+ org.opendaylight.controller.thirdpartycom.sun.jersey.jersey-servlet
diff --git a/opendaylight/commons/protocol-framework/pom.xml b/opendaylight/commons/protocol-framework/pom.xml
index f70698731a..774bc7c23f 100644
--- a/opendaylight/commons/protocol-framework/pom.xml
+++ b/opendaylight/commons/protocol-framework/pom.xml
@@ -91,6 +91,11 @@
netty-event-executor-configtest
+
+ ch.qos.logback
+ logback-classic
+ test
+
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java
index a62bd7da06..a05d02cd09 100644
--- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java
+++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java
@@ -7,12 +7,19 @@
*/
package org.opendaylight.protocol.framework;
+import java.io.Closeable;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.google.common.base.Preconditions;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
-import io.netty.channel.Channel;
import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
@@ -28,13 +35,6 @@ import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.concurrent.Promise;
-import java.io.Closeable;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* Dispatcher class for creating servers and clients. The idea is to first create servers and clients and the run the
* start method that will handle sockets in different thread.
@@ -155,7 +155,7 @@ public abstract class AbstractDispatcher, L extends
*/
protected Future createClient(final InetSocketAddress address, final ReconnectStrategy strategy, final PipelineInitializer initializer) {
final Bootstrap b = new Bootstrap();
- final ProtocolSessionPromise p = new ProtocolSessionPromise(executor, address, strategy, b);
+ final ProtocolSessionPromise p = new ProtocolSessionPromise<>(executor, address, strategy, b);
b.option(ChannelOption.SO_KEEPALIVE, true).handler(
new ChannelInitializer() {
@Override
@@ -165,18 +165,36 @@ public abstract class AbstractDispatcher, L extends
});
customizeBootstrap(b);
+ setWorkerGroup(b);
+ setChannelFactory(b);
+
+ p.connect();
+ LOG.debug("Client created.");
+ return p;
+ }
+ private void setWorkerGroup(final Bootstrap b) {
if (b.group() == null) {
b.group(workerGroup);
}
+ }
- // There is no way to detect if this was already set by
- // customizeBootstrap()
- try {
- b.channel(NioSocketChannel.class);
- } catch (IllegalStateException e) {
- LOG.trace("Not overriding channelFactory on bootstrap {}", b, e);
- }
+ /**
+ * Create a client but use a pre-configured bootstrap.
+ * This method however replaces the ChannelInitializer in the bootstrap. All other configuration is preserved.
+ *
+ * @param address remote address
+ */
+ protected Future createClient(final InetSocketAddress address, final ReconnectStrategy strategy, final Bootstrap bootstrap, final PipelineInitializer initializer) {
+ final ProtocolSessionPromise p = new ProtocolSessionPromise<>(executor, address, strategy, bootstrap);
+
+ bootstrap.handler(
+ new ChannelInitializer() {
+ @Override
+ protected void initChannel(final SocketChannel ch) {
+ initializer.initializeChannel(ch, p);
+ }
+ });
p.connect();
LOG.debug("Client created.");
@@ -195,6 +213,9 @@ public abstract class AbstractDispatcher, L extends
}
/**
+ *
+ * @deprecated use {@link org.opendaylight.protocol.framework.AbstractDispatcher#createReconnectingClient(java.net.InetSocketAddress, ReconnectStrategyFactory, org.opendaylight.protocol.framework.AbstractDispatcher.PipelineInitializer)} with only one reconnectStrategyFactory instead.
+ *
* Creates a client.
*
* @param address remote address
@@ -204,15 +225,47 @@ public abstract class AbstractDispatcher, L extends
* @return Future representing the reconnection task. It will report completion based on reestablishStrategy, e.g.
* success if it indicates no further attempts should be made and failure if it reports an error
*/
+ @Deprecated
protected Future createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory connectStrategyFactory,
final ReconnectStrategy reestablishStrategy, final PipelineInitializer initializer) {
+ return createReconnectingClient(address, connectStrategyFactory, initializer);
+ }
- final ReconnectPromise p = new ReconnectPromise(GlobalEventExecutor.INSTANCE, this, address, connectStrategyFactory, reestablishStrategy, initializer);
- p.connect();
+ /**
+ * Creates a reconnecting client.
+ *
+ * @param address remote address
+ * @param connectStrategyFactory Factory for creating reconnection strategy for every reconnect attempt
+ *
+ * @return Future representing the reconnection task. It will report completion based on reestablishStrategy, e.g.
+ * success if it indicates no further attempts should be made and failure if it reports an error
+ */
+ protected Future createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory connectStrategyFactory,
+ final PipelineInitializer initializer) {
+ final Bootstrap b = new Bootstrap();
+
+ final ReconnectPromise p = new ReconnectPromise<>(GlobalEventExecutor.INSTANCE, this, address, connectStrategyFactory, b, initializer);
+
+ b.option(ChannelOption.SO_KEEPALIVE, true);
+ customizeBootstrap(b);
+ setWorkerGroup(b);
+ setChannelFactory(b);
+
+ p.connect();
return p;
}
+ private void setChannelFactory(final Bootstrap b) {
+ // There is no way to detect if this was already set by
+ // customizeBootstrap()
+ try {
+ b.channel(NioSocketChannel.class);
+ } catch (final IllegalStateException e) {
+ LOG.trace("Not overriding channelFactory on bootstrap {}", b, e);
+ }
+ }
+
/**
* @deprecated Should only be used with {@link AbstractDispatcher#AbstractDispatcher()}
*/
@@ -225,5 +278,4 @@ public abstract class AbstractDispatcher, L extends
this.bossGroup.shutdownGracefully();
}
}
-
}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java
index a78274cca0..a38db61ead 100644
--- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java
+++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java
@@ -7,6 +7,7 @@
*/
package org.opendaylight.protocol.framework;
+import com.google.common.base.Preconditions;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
@@ -16,17 +17,12 @@ import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.concurrent.Promise;
-
import java.net.InetSocketAddress;
-
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-
@ThreadSafe
final class ProtocolSessionPromise> extends DefaultPromise {
private static final Logger LOG = LoggerFactory.getLogger(ProtocolSessionPromise.class);
@@ -54,72 +50,12 @@ final class ProtocolSessionPromise> extends Default
LOG.debug("Promise {} attempting connect for {}ms", lock, timeout);
this.b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout);
- this.pending = this.b.connect(this.address).addListener(new ChannelFutureListener() {
- @Override
- public void operationComplete(final ChannelFuture cf) throws Exception {
- synchronized (lock) {
-
- LOG.debug("Promise {} connection resolved", lock);
-
- // Triggered when a connection attempt is resolved.
- Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(cf));
-
- /*
- * The promise we gave out could have been cancelled,
- * which cascades to the connect getting cancelled,
- * but there is a slight race window, where the connect
- * is already resolved, but the listener has not yet
- * been notified -- cancellation at that point won't
- * stop the notification arriving, so we have to close
- * the race here.
- */
- if (isCancelled()) {
- if (cf.isSuccess()) {
- LOG.debug("Closing channel for cancelled promise {}", lock);
- cf.channel().close();
- }
- return;
- }
-
- if (!cf.isSuccess()) {
- LOG.debug("Attempt to connect to {} failed", ProtocolSessionPromise.this.address, cf.cause());
-
- final Future rf = ProtocolSessionPromise.this.strategy.scheduleReconnect(cf.cause());
- rf.addListener(new FutureListener() {
- @Override
- public void operationComplete(final Future sf) {
- synchronized (lock) {
- // Triggered when a connection attempt is to be made.
- Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(sf));
-
- /*
- * The promise we gave out could have been cancelled,
- * which cascades to the reconnect attempt getting
- * cancelled, but there is a slight race window, where
- * the reconnect attempt is already enqueued, but the
- * listener has not yet been notified -- if cancellation
- * happens at that point, we need to catch it here.
- */
- if (!isCancelled()) {
- if (sf.isSuccess()) {
- connect();
- } else {
- setFailure(sf.cause());
- }
- }
- }
- }
- });
-
- ProtocolSessionPromise.this.pending = rf;
- } else {
- LOG.debug("Promise {} connection successful", lock);
- }
- }
- }
- });
+ final ChannelFuture connectFuture = this.b.connect(this.address);
+ // Add listener that attempts reconnect by invoking this method again.
+ connectFuture.addListener(new BootstrapConnectListener(lock));
+ this.pending = connectFuture;
} catch (final Exception e) {
- LOG.info("Failed to connect to {}", e);
+ LOG.info("Failed to connect to {}", address, e);
setFailure(e);
}
}
@@ -140,4 +76,79 @@ final class ProtocolSessionPromise> extends Default
this.strategy.reconnectSuccessful();
return super.setSuccess(result);
}
+
+ private class BootstrapConnectListener implements ChannelFutureListener {
+ private final Object lock;
+
+ public BootstrapConnectListener(final Object lock) {
+ this.lock = lock;
+ }
+
+ @Override
+ public void operationComplete(final ChannelFuture cf) throws Exception {
+ synchronized (lock) {
+
+ LOG.debug("Promise {} connection resolved", lock);
+
+ // Triggered when a connection attempt is resolved.
+ Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(cf));
+
+ /*
+ * The promise we gave out could have been cancelled,
+ * which cascades to the connect getting cancelled,
+ * but there is a slight race window, where the connect
+ * is already resolved, but the listener has not yet
+ * been notified -- cancellation at that point won't
+ * stop the notification arriving, so we have to close
+ * the race here.
+ */
+ if (isCancelled()) {
+ if (cf.isSuccess()) {
+ LOG.debug("Closing channel for cancelled promise {}", lock);
+ cf.channel().close();
+ }
+ return;
+ }
+
+ if(cf.isSuccess()) {
+ LOG.debug("Promise {} connection successful", lock);
+ return;
+ }
+
+ LOG.debug("Attempt to connect to {} failed", ProtocolSessionPromise.this.address, cf.cause());
+
+ final Future rf = ProtocolSessionPromise.this.strategy.scheduleReconnect(cf.cause());
+ rf.addListener(new ReconnectingStrategyListener());
+ ProtocolSessionPromise.this.pending = rf;
+ }
+ }
+
+ private class ReconnectingStrategyListener implements FutureListener {
+ @Override
+ public void operationComplete(final Future sf) {
+ synchronized (lock) {
+ // Triggered when a connection attempt is to be made.
+ Preconditions.checkState(ProtocolSessionPromise.this.pending.equals(sf));
+
+ /*
+ * The promise we gave out could have been cancelled,
+ * which cascades to the reconnect attempt getting
+ * cancelled, but there is a slight race window, where
+ * the reconnect attempt is already enqueued, but the
+ * listener has not yet been notified -- if cancellation
+ * happens at that point, we need to catch it here.
+ */
+ if (!isCancelled()) {
+ if (sf.isSuccess()) {
+ connect();
+ } else {
+ setFailure(sf.cause());
+ }
+ }
+ }
+ }
+ }
+
+ }
+
}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java
index 1fa6a81753..fe1012f443 100644
--- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java
+++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java
@@ -7,176 +7,100 @@
*/
package org.opendaylight.protocol.framework;
-import io.netty.channel.ChannelFuture;
+import com.google.common.base.Preconditions;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.FutureListener;
import io.netty.util.concurrent.Promise;
-
-import java.io.Closeable;
import java.net.InetSocketAddress;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.opendaylight.protocol.framework.AbstractDispatcher.PipelineInitializer;
-
-import com.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
final class ReconnectPromise, L extends SessionListener, ?, ?>> extends DefaultPromise {
+ private static final Logger LOG = LoggerFactory.getLogger(ReconnectPromise.class);
+
private final AbstractDispatcher dispatcher;
private final InetSocketAddress address;
private final ReconnectStrategyFactory strategyFactory;
- private final ReconnectStrategy strategy;
- private final PipelineInitializer initializer;
+ private final Bootstrap b;
+ private final AbstractDispatcher.PipelineInitializer initializer;
private Future> pending;
- private final AtomicBoolean negotiationFinished = new AtomicBoolean(false);
-
public ReconnectPromise(final EventExecutor executor, final AbstractDispatcher dispatcher, final InetSocketAddress address,
- final ReconnectStrategyFactory connectStrategyFactory, final ReconnectStrategy reestablishStrategy,
- final PipelineInitializer initializer) {
+ final ReconnectStrategyFactory connectStrategyFactory, final Bootstrap b, final AbstractDispatcher.PipelineInitializer initializer) {
super(executor);
+ this.b = b;
+ this.initializer = Preconditions.checkNotNull(initializer);
this.dispatcher = Preconditions.checkNotNull(dispatcher);
this.address = Preconditions.checkNotNull(address);
this.strategyFactory = Preconditions.checkNotNull(connectStrategyFactory);
- this.strategy = Preconditions.checkNotNull(reestablishStrategy);
- this.initializer = Preconditions.checkNotNull(initializer);
}
- // FIXME: BUG-190: refactor
-
synchronized void connect() {
- negotiationFinished.set(false);
-
final ReconnectStrategy cs = this.strategyFactory.createReconnectStrategy();
- final ReconnectStrategy rs = new ReconnectStrategy() {
- @Override
- public Future scheduleReconnect(final Throwable cause) {
- return cs.scheduleReconnect(cause);
- }
- @Override
- public void reconnectSuccessful() {
- cs.reconnectSuccessful();
- }
-
- @Override
- public int getConnectTimeout() throws Exception {
- final int cst = cs.getConnectTimeout();
- final int rst = ReconnectPromise.this.strategy.getConnectTimeout();
-
- if (cst == 0) {
- return rst;
- }
- if (rst == 0) {
- return cst;
- }
- return Math.min(cst, rst);
- }
- };
-
- final Future cf = this.dispatcher.createClient(this.address, rs, new PipelineInitializer() {
+ // Set up a client with pre-configured bootstrap, but add a closed channel handler into the pipeline to support reconnect attempts
+ pending = this.dispatcher.createClient(this.address, cs, b, new AbstractDispatcher.PipelineInitializer() {
@Override
public void initializeChannel(final SocketChannel channel, final Promise promise) {
- addChannelClosedListener(channel.closeFuture());
initializer.initializeChannel(channel, promise);
+
+ // add closed channel handler
+ channel.pipeline().addFirst(new ClosedChannelHandler(ReconnectPromise.this));
}
});
+ }
- final Object lock = this;
- this.pending = cf;
+ /**
+ *
+ * @return true if initial connection was established successfully, false if initial connection failed due to e.g. Connection refused, Negotiation failed
+ */
+ private boolean isInitialConnectFinished() {
+ Preconditions.checkNotNull(pending);
+ return pending.isDone() && pending.isSuccess();
+ }
- cf.addListener(new FutureListener() {
+ @Override
+ public synchronized boolean cancel(final boolean mayInterruptIfRunning) {
+ if (super.cancel(mayInterruptIfRunning)) {
+ Preconditions.checkNotNull(pending);
+ this.pending.cancel(mayInterruptIfRunning);
+ return true;
+ }
- @Override
- public void operationComplete(final Future future) {
- synchronized (lock) {
- if (!future.isSuccess()) {
- final Future rf = ReconnectPromise.this.strategy.scheduleReconnect(cf.cause());
-
- if(rf == null) {
- // This should reflect: no more reconnecting strategies, enough
- // Currently all reconnect strategies fail with exception, should return null
- return;
- }
-
- ReconnectPromise.this.pending = rf;
-
- rf.addListener(new FutureListener() {
- @Override
- public void operationComplete(final Future sf) {
- synchronized (lock) {
- /*
- * The promise we gave out could have been cancelled,
- * which cascades to the reconnect attempt getting
- * cancelled, but there is a slight race window, where
- * the reconnect attempt is already enqueued, but the
- * listener has not yet been notified -- if cancellation
- * happens at that point, we need to catch it here.
- */
- if (!isCancelled()) {
- if (sf.isSuccess()) {
- connect();
- } else {
- setFailure(sf.cause());
- }
- }
- }
- }
- });
- } else {
- /*
- * FIXME: BUG-190: we have a slight race window with cancellation
- * here. Analyze and define its semantics.
- */
- ReconnectPromise.this.strategy.reconnectSuccessful();
- negotiationFinished.set(true);
- }
- }
- }
- });
+ return false;
}
- private final ClosedChannelListener closedChannelListener = new ClosedChannelListener();
-
- class ClosedChannelListener implements Closeable, FutureListener {
+ /**
+ * Channel handler that responds to channelInactive event and reconnects the session.
+ * Only if the initial connection was successfully established and promise was not canceled.
+ */
+ private static final class ClosedChannelHandler extends ChannelInboundHandlerAdapter {
+ private final ReconnectPromise, ?> promise;
- private final AtomicBoolean stop = new AtomicBoolean(false);
+ public ClosedChannelHandler(final ReconnectPromise, ?> promise) {
+ this.promise = promise;
+ }
@Override
- public void operationComplete(final Future future) throws Exception {
- if (stop.get()) {
+ public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
+ if (promise.isCancelled()) {
return;
}
- // Start reconnecting crashed session after negotiation was successful
- if (!negotiationFinished.get()) {
+ // Check if initial connection was fully finished. If the session was dropped during negotiation, reconnect will not happen.
+ // Session can be dropped during negotiation on purpose by the client side and would make no sense to initiate reconnect
+ if (promise.isInitialConnectFinished() == false) {
return;
}
- connect();
- }
-
- @Override
- public void close() {
- this.stop.set(true);
+ LOG.debug("Reconnecting after connection to {} was dropped", promise.address);
+ promise.connect();
}
}
- private void addChannelClosedListener(final ChannelFuture channelFuture) {
- channelFuture.addListener(closedChannelListener);
- }
-
- @Override
- public synchronized boolean cancel(final boolean mayInterruptIfRunning) {
- closedChannelListener.close();
-
- if (super.cancel(mayInterruptIfRunning)) {
- this.pending.cancel(mayInterruptIfRunning);
- return true;
- }
-
- return false;
- }
}
diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java
index 3c429fc774..a756a0da7e 100644
--- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java
+++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java
@@ -10,7 +10,7 @@ package org.opendaylight.protocol.framework;
import java.util.EventListener;
/**
- * Listener that receives session state informations. This interface should be
+ * Listener that receives session state information. This interface should be
* implemented by a protocol specific abstract class, that is extended by
* a final class that implements the methods.
*/
diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java
index bead1ee49e..63026e384c 100644
--- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java
+++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/ServerTest.java
@@ -9,6 +9,14 @@ package org.opendaylight.protocol.framework;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
@@ -16,50 +24,139 @@ import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.concurrent.Promise;
-
+import io.netty.util.concurrent.SucceededFuture;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
public class ServerTest {
SimpleDispatcher clientDispatcher, dispatcher;
- final SimpleSessionListener pce = new SimpleSessionListener();
-
SimpleSession session = null;
ChannelFuture server = null;
InetSocketAddress serverAddress;
private NioEventLoopGroup eventLoopGroup;
-
+ // Dedicated loop group for server, needed for testing reconnection client
+ // With dedicated server group we can simulate session drop by shutting only the server group down
+ private NioEventLoopGroup serverLoopGroup;
@Before
public void setUp() {
final int port = 10000 + (int)(10000 * Math.random());
serverAddress = new InetSocketAddress("127.0.0.1", port);
eventLoopGroup = new NioEventLoopGroup();
+ serverLoopGroup = new NioEventLoopGroup();
+ }
+
+ @After
+ public void tearDown() throws IOException, InterruptedException, ExecutionException {
+ if(server != null) {
+ this.server.channel().close();
+ }
+ this.eventLoopGroup.shutdownGracefully().get();
+ this.serverLoopGroup.shutdownGracefully().get();
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ throw new RuntimeException(e);
+ }
}
@Test
- public void testConnectionEstablished() throws Exception {
+ public void testConnectionRefused() throws Exception {
+ this.clientDispatcher = getClientDispatcher();
+
+ final ReconnectStrategy mockReconnectStrategy = getMockedReconnectStrategy();
+
+ this.clientDispatcher.createClient(this.serverAddress,
+ mockReconnectStrategy, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ });
+
+ Mockito.verify(mockReconnectStrategy, timeout(5000).atLeast(2)).scheduleReconnect(any(Throwable.class));
+ }
+
+ @Test
+ public void testConnectionReestablishInitial() throws Exception {
+ this.clientDispatcher = getClientDispatcher();
+
+ final ReconnectStrategy mockReconnectStrategy = getMockedReconnectStrategy();
+
+ this.clientDispatcher.createClient(this.serverAddress,
+ mockReconnectStrategy, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ });
+
+ Mockito.verify(mockReconnectStrategy, timeout(5000).atLeast(2)).scheduleReconnect(any(Throwable.class));
+
+ final Promise p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+ this.dispatcher = getServerDispatcher(p);
+
+ this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ });
+
+ this.server.get();
+
+ assertEquals(true, p.get(3, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testConnectionDrop() throws Exception {
final Promise p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
- this.dispatcher = new SimpleDispatcher(new SessionNegotiatorFactory() {
+ this.dispatcher = getServerDispatcher(p);
+ this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory() {
@Override
- public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
- final Channel channel, final Promise promise) {
- p.setSuccess(true);
- return new SimpleSessionNegotiator(promise, channel);
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
}
- }, new DefaultPromise(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+ });
+
+ this.server.get();
+
+ this.clientDispatcher = getClientDispatcher();
+
+ final ReconnectStrategy reconnectStrategy = getMockedReconnectStrategy();
+ this.session = this.clientDispatcher.createClient(this.serverAddress,
+ reconnectStrategy, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ }).get(6, TimeUnit.SECONDS);
+
+ assertEquals(true, p.get(3, TimeUnit.SECONDS));
+
+ shutdownServer();
+
+ // No reconnect should be scheduled after server drops connection with not-reconnecting client
+ verify(reconnectStrategy, times(0)).scheduleReconnect(any(Throwable.class));
+ }
+
+ @Test
+ public void testConnectionReestablishAfterDrop() throws Exception {
+ final Promise p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+
+ this.dispatcher = getServerDispatcher(p);
this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory() {
@Override
@@ -70,13 +167,42 @@ public class ServerTest {
this.server.get();
- this.clientDispatcher = new SimpleDispatcher(new SessionNegotiatorFactory() {
+ this.clientDispatcher = getClientDispatcher();
+
+ final ReconnectStrategyFactory reconnectStrategyFactory = mock(ReconnectStrategyFactory.class);
+ final ReconnectStrategy reconnectStrategy = getMockedReconnectStrategy();
+ doReturn(reconnectStrategy).when(reconnectStrategyFactory).createReconnectStrategy();
+
+ this.clientDispatcher.createReconnectingClient(this.serverAddress,
+ reconnectStrategyFactory, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ });
+
+ assertEquals(true, p.get(3, TimeUnit.SECONDS));
+ shutdownServer();
+
+ verify(reconnectStrategyFactory, timeout(20000).atLeast(2)).createReconnectStrategy();
+ }
+
+ @Test
+ public void testConnectionEstablished() throws Exception {
+ final Promise p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+
+ this.dispatcher = getServerDispatcher(p);
+
+ this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory() {
@Override
- public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
- final Channel channel, final Promise promise) {
- return new SimpleSessionNegotiator(promise, channel);
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
}
- }, new DefaultPromise(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+ });
+
+ this.server.get();
+
+ this.clientDispatcher = getClientDispatcher();
this.session = this.clientDispatcher.createClient(this.serverAddress,
new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000), new SessionListenerFactory() {
@@ -93,15 +219,7 @@ public class ServerTest {
public void testConnectionFailed() throws IOException, InterruptedException, ExecutionException, TimeoutException {
final Promise p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
- this.dispatcher = new SimpleDispatcher(new SessionNegotiatorFactory() {
-
- @Override
- public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
- final Channel channel, final Promise promise) {
- p.setSuccess(true);
- return new SimpleSessionNegotiator(promise, channel);
- }
- }, new DefaultPromise(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+ this.dispatcher = getServerDispatcher(p);
this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory() {
@Override
@@ -112,13 +230,7 @@ public class ServerTest {
this.server.get();
- this.clientDispatcher = new SimpleDispatcher(new SessionNegotiatorFactory() {
- @Override
- public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
- final Channel channel, final Promise promise) {
- return new SimpleSessionNegotiator(promise, channel);
- }
- }, new DefaultPromise(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+ this.clientDispatcher = getClientDispatcher();
this.session = this.clientDispatcher.createClient(this.serverAddress,
new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, 5000), new SessionListenerFactory() {
@@ -138,14 +250,89 @@ public class ServerTest {
assertFalse(session.isSuccess());
}
- @After
- public void tearDown() throws IOException, InterruptedException {
- this.server.channel().close();
- this.eventLoopGroup.shutdownGracefully();
- try {
- Thread.sleep(500);
- } catch (final InterruptedException e) {
- throw new RuntimeException(e);
- }
+ @Test
+ public void testNegotiationFailedNoReconnect() throws Exception {
+ final Promise p = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);
+
+ this.dispatcher = getServerDispatcher(p);
+
+ this.server = this.dispatcher.createServer(this.serverAddress, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ });
+
+ this.server.get();
+
+ this.clientDispatcher = new SimpleDispatcher(new SessionNegotiatorFactory() {
+ @Override
+ public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
+ final Channel channel, final Promise promise) {
+
+ return new SimpleSessionNegotiator(promise, channel) {
+ @Override
+ protected void startNegotiation() throws Exception {
+ negotiationFailed(new IllegalStateException("Negotiation failed"));
+ }
+ };
+ }
+ }, new DefaultPromise(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+
+ final ReconnectStrategyFactory reconnectStrategyFactory = mock(ReconnectStrategyFactory.class);
+ final ReconnectStrategy reconnectStrategy = getMockedReconnectStrategy();
+ doReturn(reconnectStrategy).when(reconnectStrategyFactory).createReconnectStrategy();
+
+ this.clientDispatcher.createReconnectingClient(this.serverAddress,
+ reconnectStrategyFactory, new SessionListenerFactory() {
+ @Override
+ public SimpleSessionListener getSessionListener() {
+ return new SimpleSessionListener();
+ }
+ });
+
+
+ // Only one strategy should be created for initial connect, no more = no reconnects
+ verify(reconnectStrategyFactory, times(1)).createReconnectStrategy();
}
+
+ private SimpleDispatcher getClientDispatcher() {
+ return new SimpleDispatcher(new SessionNegotiatorFactory() {
+ @Override
+ public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
+ final Channel channel, final Promise promise) {
+ return new SimpleSessionNegotiator(promise, channel);
+ }
+ }, new DefaultPromise(GlobalEventExecutor.INSTANCE), eventLoopGroup);
+ }
+
+ private ReconnectStrategy getMockedReconnectStrategy() throws Exception {
+ final ReconnectStrategy mockReconnectStrategy = mock(ReconnectStrategy.class);
+ final Future future = new SucceededFuture<>(GlobalEventExecutor.INSTANCE, null);
+ doReturn(future).when(mockReconnectStrategy).scheduleReconnect(any(Throwable.class));
+ doReturn(5000).when(mockReconnectStrategy).getConnectTimeout();
+ doNothing().when(mockReconnectStrategy).reconnectSuccessful();
+ return mockReconnectStrategy;
+ }
+
+
+ private void shutdownServer() throws InterruptedException, ExecutionException {
+ // Shutdown server
+ server.channel().close().get();
+ // Closing server channel does not close established connections, eventLoop has to be closed as well to simulate dropped session
+ serverLoopGroup.shutdownGracefully().get();
+ }
+
+ private SimpleDispatcher getServerDispatcher(final Promise p) {
+ return new SimpleDispatcher(new SessionNegotiatorFactory() {
+
+ @Override
+ public SessionNegotiator getSessionNegotiator(final SessionListenerFactory factory,
+ final Channel channel, final Promise promise) {
+ p.setSuccess(true);
+ return new SimpleSessionNegotiator(promise, channel);
+ }
+ }, null, serverLoopGroup);
+ }
+
}
diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/SimpleDispatcher.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/SimpleDispatcher.java
index 12aac9ecc5..d83738520c 100644
--- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/SimpleDispatcher.java
+++ b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/protocol/framework/SimpleDispatcher.java
@@ -54,6 +54,10 @@ public class SimpleDispatcher extends AbstractDispatcher createReconnectingClient(final InetSocketAddress address, final ReconnectStrategyFactory strategy, final SessionListenerFactory listenerFactory) {
+ return super.createReconnectingClient(address, strategy, new SimplePipelineInitializer(listenerFactory));
+ }
+
public ChannelFuture createServer(final InetSocketAddress address, final SessionListenerFactory listenerFactory) {
return super.createServer(address, new SimplePipelineInitializer(listenerFactory));
}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java
index ec46219aaf..6050f7c070 100644
--- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java
+++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java
@@ -14,7 +14,7 @@ import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy
import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.osgi.framework.BundleContext;
/**
@@ -31,7 +31,7 @@ public class CodecRegistryProvider implements AutoCloseable {
public CodecRegistryProvider(final ClassLoadingStrategy classLoadingStrategy, final BundleContext context) {
service = new RuntimeGeneratedMappingServiceImpl(CLASS_POOL, classLoadingStrategy);
registration = OsgiRegistrationUtil.registerService(context, service,
- SchemaServiceListener.class, BindingIndependentMappingService.class);
+ SchemaContextListener.class, BindingIndependentMappingService.class);
}
public CodecRegistry getCodecRegistry() {
diff --git a/opendaylight/config/config-netty-config/pom.xml b/opendaylight/config/config-netty-config/pom.xml
new file mode 100644
index 0000000000..8dc31dcc4e
--- /dev/null
+++ b/opendaylight/config/config-netty-config/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ 4.0.0
+
+ org.opendaylight.controller
+ config-subsystem
+ 0.2.5-SNAPSHOT
+
+ config-netty-config
+ Configuration files for sal-rest-connector
+ jar
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ attach-artifacts
+
+ attach-artifact
+
+ package
+
+
+
+ ${project.build.directory}/classes/initial/00-netty.xml
+ xml
+ config
+
+
+
+
+
+
+
+
+
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.xml b/opendaylight/config/config-netty-config/src/main/resources/initial/00-netty.xml
similarity index 100%
rename from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.xml
rename to opendaylight/config/config-netty-config/src/main/resources/initial/00-netty.xml
diff --git a/opendaylight/config/pom.xml b/opendaylight/config/pom.xml
index 66bb01f051..26fac47e71 100644
--- a/opendaylight/config/pom.xml
+++ b/opendaylight/config/pom.xml
@@ -39,6 +39,7 @@
shutdown-implnetconf-config-dispatcherconfig-module-archetype
+ config-netty-config
diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml
index 541c1300f3..4d0770f8cb 100644
--- a/opendaylight/distribution/opendaylight/pom.xml
+++ b/opendaylight/distribution/opendaylight/pom.xml
@@ -745,7 +745,7 @@
generate-resources${project.build.directory}/configuration
- sal-rest-connector-config
+ sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config**\/*.xmltruefalse
@@ -1034,6 +1034,26 @@
org.opendaylight.controllersal-rest-connector-config
+
+ org.opendaylight.controller
+ config-netty-config
+
+
+ org.opendaylight.controller
+ md-sal-config
+
+
+ org.opendaylight.controller
+ netconf-config
+
+
+ org.opendaylight.controller
+ netconf-connector-config
+
+
+ org.opendaylight.controller.samples
+ toaster-config
+ org.opendaylight.controllersal-rest-docgen
@@ -1318,7 +1338,7 @@
generate-resources${project.build.directory}/configuration
- sal-rest-connector-config
+ sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config**\/*.xmltruefalse
diff --git a/opendaylight/md-sal/md-sal-config/pom.xml b/opendaylight/md-sal/md-sal-config/pom.xml
new file mode 100644
index 0000000000..2e19b5a60c
--- /dev/null
+++ b/opendaylight/md-sal/md-sal-config/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ 4.0.0
+
+ org.opendaylight.controller
+ sal-parent
+ 1.1-SNAPSHOT
+
+ md-sal-config
+ Configuration files for md-sal
+ jar
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ attach-artifacts
+
+ attach-artifact
+
+ package
+
+
+
+ ${project.build.directory}/classes/initial/01-md-sal.xml
+ xml
+ config
+
+
+
+
+
+
+
+
+
diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml b/opendaylight/md-sal/md-sal-config/src/main/resources/initial/01-md-sal.xml
similarity index 99%
rename from opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml
rename to opendaylight/md-sal/md-sal-config/src/main/resources/initial/01-md-sal.xml
index 03da7f0ccd..f25b7d91bd 100644
--- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.xml
+++ b/opendaylight/md-sal/md-sal-config/src/main/resources/initial/01-md-sal.xml
@@ -72,17 +72,7 @@
-->
-
-
+
prefix:inmemory-operational-datastore-provideroperational-store-service
@@ -157,6 +147,17 @@
+
+
diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml
index cadd8ca87d..02fbde8f18 100644
--- a/opendaylight/md-sal/pom.xml
+++ b/opendaylight/md-sal/pom.xml
@@ -32,6 +32,9 @@
sal-binding-util
+
+ md-sal-config
+
samples
@@ -66,11 +69,17 @@
sal-protocolbuffer-encoding
-
+
sal-distributed-datastore
+
+ sal-dom-xsql
+
sal-test-model
+
+
+ sal-remoterpc-connector
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java
index 641ec0582c..aa100df9d0 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java
@@ -11,10 +11,12 @@ package org.opendaylight.controller.cluster.example;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.japi.Creator;
+import com.google.common.base.Optional;
import org.opendaylight.controller.cluster.example.messages.KeyValue;
import org.opendaylight.controller.cluster.example.messages.KeyValueSaved;
import org.opendaylight.controller.cluster.example.messages.PrintRole;
import org.opendaylight.controller.cluster.example.messages.PrintState;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
import org.opendaylight.controller.cluster.raft.RaftActor;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
@@ -31,15 +33,17 @@ public class ExampleActor extends RaftActor {
private long persistIdentifier = 1;
- public ExampleActor(String id, Map peerAddresses) {
- super(id, peerAddresses);
+ public ExampleActor(String id, Map peerAddresses,
+ Optional configParams) {
+ super(id, peerAddresses, configParams);
}
- public static Props props(final String id, final Map peerAddresses){
+ public static Props props(final String id, final Map peerAddresses,
+ final Optional configParams){
return Props.create(new Creator(){
@Override public ExampleActor create() throws Exception {
- return new ExampleActor(id, peerAddresses);
+ return new ExampleActor(id, peerAddresses, configParams);
}
});
}
@@ -56,10 +60,12 @@ public class ExampleActor extends RaftActor {
}
} else if (message instanceof PrintState) {
- LOG.debug("State of the node:"+getId() + " has = "+state.size() + " entries");
+ LOG.debug("State of the node:{} has entries={}, {}",
+ getId(), state.size(), getReplicatedLogState());
} else if (message instanceof PrintRole) {
- LOG.debug(getId() + " = " + getRaftState());
+ LOG.debug("{} = {}, Peers={}", getId(), getRaftState(),getPeers());
+
} else {
super.onReceiveCommand(message);
}
@@ -83,6 +89,7 @@ public class ExampleActor extends RaftActor {
@Override protected void applySnapshot(Object snapshot) {
state.clear();
state.putAll((HashMap) snapshot);
+ LOG.debug("Snapshot applied to state :" + ((HashMap) snapshot).size());
}
@Override public void onReceiveRecover(Object message) {
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleConfigParamsImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleConfigParamsImpl.java
new file mode 100644
index 0000000000..d11377dbcb
--- /dev/null
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleConfigParamsImpl.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.example;
+
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+
+/**
+ * Implementation of ConfigParams for Example
+ */
+public class ExampleConfigParamsImpl extends DefaultConfigParamsImpl {
+ @Override
+ public long getSnapshotBatchCount() {
+ return 50;
+ }
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java
index a148ed4009..0e5d643a64 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/Main.java
@@ -11,7 +11,9 @@ package org.opendaylight.controller.cluster.example;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.PoisonPill;
+import com.google.common.base.Optional;
import org.opendaylight.controller.cluster.example.messages.KeyValue;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@@ -34,15 +36,15 @@ public class Main {
public static void main(String[] args) throws Exception{
ActorRef example1Actor =
actorSystem.actorOf(ExampleActor.props("example-1",
- withoutPeer("example-1")), "example-1");
+ withoutPeer("example-1"), Optional.absent()), "example-1");
ActorRef example2Actor =
actorSystem.actorOf(ExampleActor.props("example-2",
- withoutPeer("example-2")), "example-2");
+ withoutPeer("example-2"), Optional.absent()), "example-2");
ActorRef example3Actor =
actorSystem.actorOf(ExampleActor.props("example-3",
- withoutPeer("example-3")), "example-3");
+ withoutPeer("example-3"), Optional.absent()), "example-3");
List examples = Arrays.asList(example1Actor, example2Actor, example3Actor);
@@ -74,7 +76,8 @@ public class Main {
String actorName = "example-" + i;
examples.add(i - 1,
actorSystem.actorOf(ExampleActor.props(actorName,
- withoutPeer(actorName)), actorName));
+ withoutPeer(actorName), Optional.absent()),
+ actorName));
System.out.println("Created actor : " + actorName);
continue;
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java
index c2d0b3a6b7..fd6e192bf0 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/TestDriver.java
@@ -2,8 +2,10 @@ package org.opendaylight.controller.cluster.example;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
+import com.google.common.base.Optional;
import org.opendaylight.controller.cluster.example.messages.PrintRole;
import org.opendaylight.controller.cluster.example.messages.PrintState;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
import org.opendaylight.controller.cluster.raft.client.messages.AddRaftPeer;
import org.opendaylight.controller.cluster.raft.client.messages.RemoveRaftPeer;
@@ -11,14 +13,13 @@ import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
-import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
/**
* This is a test driver for testing akka-raft implementation
* Its uses ExampleActors and threads to push content(key-vals) to these actors
* Each ExampleActor can have one or more ClientActors. Each ClientActor spawns
- * a thread and starts push logs to the actor its assignged to.
+ * a thread and starts push logs to the actor its assigned to.
*/
public class TestDriver {
@@ -26,7 +27,9 @@ public class TestDriver {
private static Map allPeers = new HashMap<>();
private static Map clientActorRefs = new HashMap();
private static Map actorRefs = new HashMap();
- private static LogGenerator logGenerator = new LogGenerator();;
+ private static LogGenerator logGenerator = new LogGenerator();
+ private int nameCounter = 0;
+ private static ConfigParams configParams = new ExampleConfigParamsImpl();
/**
* Create nodes, add clients and start logging.
@@ -35,6 +38,7 @@ public class TestDriver {
* createNodes:{num}
* addNodes:{num}
* stopNode:{nodeName}
+ * reinstateNode:{nodeName}
* addClients:{num}
* addClientsToNode:{nodeName, num}
* startLogging
@@ -83,6 +87,10 @@ public class TestDriver {
String[] arr = command.split(":");
td.stopNode(arr[1]);
+ } else if (command.startsWith("reinstateNode")) {
+ String[] arr = command.split(":");
+ td.reinstateNode(arr[1]);
+
} else if (command.startsWith("startLogging")) {
td.startAllLogging();
@@ -106,15 +114,19 @@ public class TestDriver {
}
}
+ public static ActorRef createExampleActor(String name) {
+ return actorSystem.actorOf(ExampleActor.props(name, withoutPeer(name),
+ Optional.of(configParams)), name);
+ }
+
public void createNodes(int num) {
for (int i=0; i < num; i++) {
- int rand = getUnusedRandom(num);
- allPeers.put("example-"+rand, "akka://default/user/example-"+rand);
+ nameCounter = nameCounter + 1;
+ allPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
}
for (String s : allPeers.keySet()) {
- ActorRef exampleActor = actorSystem.actorOf(
- ExampleActor.props(s, withoutPeer(s)), s);
+ ActorRef exampleActor = createExampleActor(s);
actorRefs.put(s, exampleActor);
System.out.println("Created node:"+s);
@@ -125,15 +137,14 @@ public class TestDriver {
public void addNodes(int num) {
Map newPeers = new HashMap<>();
for (int i=0; i < num; i++) {
- int rand = getUnusedRandom(num);
- newPeers.put("example-"+rand, "akka://default/user/example-"+rand);
- allPeers.put("example-"+rand, "akka://default/user/example-"+rand);
+ nameCounter = nameCounter + 1;
+ newPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
+ allPeers.put("example-"+nameCounter, "akka://default/user/example-"+nameCounter);
}
Map newActorRefs = new HashMap(num);
for (Map.Entry entry : newPeers.entrySet()) {
- ActorRef exampleActor = actorSystem.actorOf(
- ExampleActor.props(entry.getKey(), withoutPeer(entry.getKey())), entry.getKey());
+ ActorRef exampleActor = createExampleActor(entry.getKey());
newActorRefs.put(entry.getKey(), exampleActor);
//now also add these new nodes as peers from the previous nodes
@@ -165,7 +176,7 @@ public class TestDriver {
public void addClientsToNode(String actorName, int num) {
ActorRef actorRef = actorRefs.get(actorName);
for (int i=0; i < num; i++) {
- String clientName = "client-" + i + "-" + actorRef;
+ String clientName = "client-" + i + "-" + actorName;
clientActorRefs.put(clientName,
actorSystem.actorOf(ClientActor.props(actorRef), clientName));
System.out.println("Added client-node:" + clientName);
@@ -174,11 +185,13 @@ public class TestDriver {
public void stopNode(String actorName) {
ActorRef actorRef = actorRefs.get(actorName);
- String clientName = "client-"+actorName;
- if(clientActorRefs.containsKey(clientName)) {
- actorSystem.stop(clientActorRefs.get(clientName));
- clientActorRefs.remove(clientName);
+
+ for (Map.Entry entry : clientActorRefs.entrySet()) {
+ if (entry.getKey().endsWith(actorName)) {
+ actorSystem.stop(entry.getValue());
+ }
}
+
actorSystem.stop(actorRef);
actorRefs.remove(actorName);
@@ -187,7 +200,21 @@ public class TestDriver {
}
allPeers.remove(actorName);
+ }
+ public void reinstateNode(String actorName) {
+ String address = "akka://default/user/"+actorName;
+ allPeers.put(actorName, address);
+
+ ActorRef exampleActor = createExampleActor(actorName);
+
+ for (ActorRef actor : actorRefs.values()) {
+ actor.tell(new AddRaftPeer(actorName, address), null);
+ }
+
+ actorRefs.put(actorName, exampleActor);
+
+ addClientsToNode(actorName, 1);
}
public void startAllLogging() {
@@ -232,14 +259,6 @@ public class TestDriver {
return null;
}
- private int getUnusedRandom(int num) {
- int rand = -1;
- do {
- rand = (new Random()).nextInt(num * num);
- } while (allPeers.keySet().contains("example-"+rand));
-
- return rand;
- }
private static Map withoutPeer(String peerId) {
Map without = new ConcurrentHashMap<>(allPeers);
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java
new file mode 100644
index 0000000000..24bfa3de21
--- /dev/null
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.raft;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract class handling the mapping of
+ * logical LogEntry Index and the physical list index.
+ */
+public abstract class AbstractReplicatedLogImpl implements ReplicatedLog {
+
+ protected final List journal;
+ protected final Object snapshot;
+ protected long snapshotIndex = -1;
+ protected long snapshotTerm = -1;
+
+ public AbstractReplicatedLogImpl(Object state, long snapshotIndex,
+ long snapshotTerm, List unAppliedEntries) {
+ this.snapshot = state;
+ this.snapshotIndex = snapshotIndex;
+ this.snapshotTerm = snapshotTerm;
+ this.journal = new ArrayList<>(unAppliedEntries);
+ }
+
+
+ public AbstractReplicatedLogImpl() {
+ this.snapshot = null;
+ this.journal = new ArrayList<>();
+ }
+
+ protected int adjustedIndex(long logEntryIndex) {
+ if(snapshotIndex < 0){
+ return (int) logEntryIndex;
+ }
+ return (int) (logEntryIndex - (snapshotIndex + 1));
+ }
+
+ @Override
+ public ReplicatedLogEntry get(long logEntryIndex) {
+ int adjustedIndex = adjustedIndex(logEntryIndex);
+
+ if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
+ // physical index should be less than list size and >= 0
+ return null;
+ }
+
+ return journal.get(adjustedIndex);
+ }
+
+ @Override
+ public ReplicatedLogEntry last() {
+ if (journal.isEmpty()) {
+ return null;
+ }
+ // get the last entry directly from the physical index
+ return journal.get(journal.size() - 1);
+ }
+
+ @Override
+ public long lastIndex() {
+ if (journal.isEmpty()) {
+ // it can happen that after snapshot, all the entries of the
+ // journal are trimmed till lastApplied, so lastIndex = snapshotIndex
+ return snapshotIndex;
+ }
+ return last().getIndex();
+ }
+
+ @Override
+ public long lastTerm() {
+ if (journal.isEmpty()) {
+ // it can happen that after snapshot, all the entries of the
+ // journal are trimmed till lastApplied, so lastTerm = snapshotTerm
+ return snapshotTerm;
+ }
+ return last().getTerm();
+ }
+
+ @Override
+ public void removeFrom(long logEntryIndex) {
+ int adjustedIndex = adjustedIndex(logEntryIndex);
+ if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
+ // physical index should be less than list size and >= 0
+ return;
+ }
+ journal.subList(adjustedIndex , journal.size()).clear();
+ }
+
+ @Override
+ public void append(ReplicatedLogEntry replicatedLogEntry) {
+ journal.add(replicatedLogEntry);
+ }
+
+ @Override
+ public List getFrom(long logEntryIndex) {
+ int adjustedIndex = adjustedIndex(logEntryIndex);
+ int size = journal.size();
+ List entries = new ArrayList<>(100);
+ if (adjustedIndex >= 0 && adjustedIndex < size) {
+ // physical index should be less than list size and >= 0
+ entries.addAll(journal.subList(adjustedIndex, size));
+ }
+ return entries;
+ }
+
+ @Override
+ public long size() {
+ return journal.size();
+ }
+
+ @Override
+ public boolean isPresent(long logEntryIndex) {
+ if (logEntryIndex > lastIndex()) {
+ // if the request logical index is less than the last present in the list
+ return false;
+ }
+ int adjustedIndex = adjustedIndex(logEntryIndex);
+ return (adjustedIndex >= 0);
+ }
+
+ @Override
+ public boolean isInSnapshot(long logEntryIndex) {
+ return logEntryIndex <= snapshotIndex;
+ }
+
+ @Override
+ public Object getSnapshot() {
+ return snapshot;
+ }
+
+ @Override
+ public long getSnapshotIndex() {
+ return snapshotIndex;
+ }
+
+ @Override
+ public long getSnapshotTerm() {
+ return snapshotTerm;
+ }
+
+ @Override
+ public abstract void appendAndPersist(ReplicatedLogEntry replicatedLogEntry);
+
+ @Override
+ public abstract void removeFromAndPersist(long index);
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java
new file mode 100644
index 0000000000..4c6434aec4
--- /dev/null
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ConfigParams.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.raft;
+
+import scala.concurrent.duration.FiniteDuration;
+
+/**
+ * Configuration Parameter interface for configuring the Raft consensus system
+ *
+ * Any component using this implementation might want to provide an implementation of
+ * this interface to configure
+ *
+ * A default implementation will be used if none is provided.
+ *
+ * @author Kamal Rameshan
+ */
+public interface ConfigParams {
+ /**
+ * The minimum number of entries to be present in the in-memory Raft log
+ * for a snapshot to be taken
+ *
+ * @return long
+ */
+ public long getSnapshotBatchCount();
+
+ /**
+ * The interval at which a heart beat message will be sent to the remote
+ * RaftActor
+ *
+ * @return FiniteDuration
+ */
+ public FiniteDuration getHeartBeatInterval();
+
+ /**
+ * The interval in which a new election would get triggered if no leader is found
+ *
+ * Normally its set to atleast twice the heart beat interval
+ *
+ * @return FiniteDuration
+ */
+ public FiniteDuration getElectionTimeOutInterval();
+
+ /**
+ * The maximum election time variance. The election is scheduled using both
+ * the Election Timeout and Variance
+ *
+ * @return int
+ */
+ public int getElectionTimeVariance();
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java
new file mode 100644
index 0000000000..c633337226
--- /dev/null
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/DefaultConfigParamsImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.raft;
+
+import scala.concurrent.duration.FiniteDuration;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Default implementation of the ConfigParams
+ *
+ * If no implementation is provided for ConfigParams, then this will be used.
+ */
+public class DefaultConfigParamsImpl implements ConfigParams {
+
+ private static final int SNAPSHOT_BATCH_COUNT = 100000;
+
+ /**
+ * The maximum election time variance
+ */
+ private static final int ELECTION_TIME_MAX_VARIANCE = 100;
+
+
+ /**
+ * The interval at which a heart beat message will be sent to the remote
+ * RaftActor
+ *
+ * Since this is set to 100 milliseconds the Election timeout should be
+ * at least 200 milliseconds
+ */
+ protected static final FiniteDuration HEART_BEAT_INTERVAL =
+ new FiniteDuration(100, TimeUnit.MILLISECONDS);
+
+
+ @Override
+ public long getSnapshotBatchCount() {
+ return SNAPSHOT_BATCH_COUNT;
+ }
+
+ @Override
+ public FiniteDuration getHeartBeatInterval() {
+ return HEART_BEAT_INTERVAL;
+ }
+
+
+ @Override
+ public FiniteDuration getElectionTimeOutInterval() {
+ // returns 2 times the heart beat interval
+ return HEART_BEAT_INTERVAL.$times(2);
+ }
+
+ @Override
+ public int getElectionTimeVariance() {
+ return ELECTION_TIME_MAX_VARIANCE;
+ }
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
index 15239795a8..70b85b4627 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java
@@ -19,6 +19,10 @@ import akka.persistence.SaveSnapshotSuccess;
import akka.persistence.SnapshotOffer;
import akka.persistence.SnapshotSelectionCriteria;
import akka.persistence.UntypedPersistentActor;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.Replicate;
+import com.google.common.base.Optional;
import org.opendaylight.controller.cluster.raft.behaviors.Candidate;
import org.opendaylight.controller.cluster.raft.behaviors.Follower;
import org.opendaylight.controller.cluster.raft.behaviors.Leader;
@@ -26,14 +30,10 @@ import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
import org.opendaylight.controller.cluster.raft.client.messages.AddRaftPeer;
import org.opendaylight.controller.cluster.raft.client.messages.FindLeader;
import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply;
-import org.opendaylight.controller.cluster.raft.internal.messages.ApplySnapshot;
import org.opendaylight.controller.cluster.raft.client.messages.RemoveRaftPeer;
-import org.opendaylight.controller.cluster.raft.internal.messages.ApplyState;
-import org.opendaylight.controller.cluster.raft.internal.messages.Replicate;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -100,14 +100,22 @@ public abstract class RaftActor extends UntypedPersistentActor {
public RaftActor(String id, Map peerAddresses) {
+ this(id, peerAddresses, Optional.absent());
+ }
+
+ public RaftActor(String id, Map peerAddresses,
+ Optional configParams) {
+
context = new RaftActorContextImpl(this.getSelf(),
- this.getContext(),
- id, new ElectionTermImpl(),
- -1, -1, replicatedLog, peerAddresses, LOG);
+ this.getContext(), id, new ElectionTermImpl(),
+ -1, -1, replicatedLog, peerAddresses,
+ (configParams.isPresent() ? configParams.get(): new DefaultConfigParamsImpl()),
+ LOG);
}
@Override public void onReceiveRecover(Object message) {
if (message instanceof SnapshotOffer) {
+ LOG.debug("SnapshotOffer called..");
SnapshotOffer offer = (SnapshotOffer) message;
Snapshot snapshot = (Snapshot) offer.snapshot();
@@ -116,6 +124,13 @@ public abstract class RaftActor extends UntypedPersistentActor {
// when we need to install it on a peer
replicatedLog = new ReplicatedLogImpl(snapshot);
+ context.setReplicatedLog(replicatedLog);
+
+ LOG.debug("Applied snapshot to replicatedLog. " +
+ "snapshotIndex={}, snapshotTerm={}, journal-size={}",
+ replicatedLog.snapshotIndex, replicatedLog.snapshotTerm,
+ replicatedLog.size());
+
// Apply the snapshot to the actors state
applySnapshot(snapshot.getState());
@@ -127,7 +142,11 @@ public abstract class RaftActor extends UntypedPersistentActor {
context.getTermInformation().update(((UpdateElectionTerm) message).getCurrentTerm(), ((UpdateElectionTerm) message).getVotedFor());
} else if (message instanceof RecoveryCompleted) {
LOG.debug(
- "Last index in log : " + replicatedLog.lastIndex());
+ "RecoveryCompleted - Switching actor to Follower - " +
+ "Last index in log:{}, snapshotIndex={}, snapshotTerm={}, " +
+ "journal-size={}",
+ replicatedLog.lastIndex(), replicatedLog.snapshotIndex,
+ replicatedLog.snapshotTerm, replicatedLog.size());
currentBehavior = switchBehavior(RaftState.Follower);
}
}
@@ -191,6 +210,15 @@ public abstract class RaftActor extends UntypedPersistentActor {
}
}
+ public java.util.Set getPeers() {
+ return context.getPeerAddresses().keySet();
+ }
+
+ protected String getReplicatedLogState() {
+ return "snapshotIndex=" + context.getReplicatedLog().getSnapshotIndex()
+ + ", snapshotTerm=" + context.getReplicatedLog().getSnapshotTerm()
+ + ", im-mem journal size=" + context.getReplicatedLog().size();
+ }
/**
@@ -250,6 +278,24 @@ public abstract class RaftActor extends UntypedPersistentActor {
return currentBehavior.state();
}
+ /**
+ * setPeerAddress sets the address of a known peer at a later time.
+ *
+ * This is to account for situations where a we know that a peer
+ * exists but we do not know an address up-front. This may also be used in
+ * situations where a known peer starts off in a different location and we
+ * need to change it's address
+ *
+ * Note that if the peerId does not match the list of peers passed to
+ * this actor during construction an IllegalStateException will be thrown.
+ *
+ * @param peerId
+ * @param peerAddress
+ */
+ protected void setPeerAddress(String peerId, String peerAddress){
+ context.setPeerAddress(peerId, peerAddress);
+ }
+
/**
@@ -325,85 +371,33 @@ public abstract class RaftActor extends UntypedPersistentActor {
}
private void trimPersistentData(long sequenceNumber) {
- // Trim snapshots
+ // Trim akka snapshots
// FIXME : Not sure how exactly the SnapshotSelectionCriteria is applied
// For now guessing that it is ANDed.
deleteSnapshots(new SnapshotSelectionCriteria(
- sequenceNumber - 100000, 43200000));
+ sequenceNumber - context.getConfigParams().getSnapshotBatchCount(), 43200000));
- // Trim journal
+ // Trim akka journal
deleteMessages(sequenceNumber);
}
- private class ReplicatedLogImpl implements ReplicatedLog {
- private final List journal;
- private final Object snapshot;
- private long snapshotIndex = -1;
- private long snapshotTerm = -1;
+ private class ReplicatedLogImpl extends AbstractReplicatedLogImpl {
public ReplicatedLogImpl(Snapshot snapshot) {
- this.snapshot = snapshot.getState();
- this.snapshotIndex = snapshot.getLastAppliedIndex();
- this.snapshotTerm = snapshot.getLastAppliedTerm();
-
- this.journal = new ArrayList<>(snapshot.getUnAppliedEntries());
+ super(snapshot.getState(),
+ snapshot.getLastAppliedIndex(), snapshot.getLastAppliedTerm(),
+ snapshot.getUnAppliedEntries());
}
public ReplicatedLogImpl() {
- this.snapshot = null;
- this.journal = new ArrayList<>();
- }
-
- @Override public ReplicatedLogEntry get(long index) {
- int adjustedIndex = adjustedIndex(index);
-
- if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
- return null;
- }
-
- return journal.get(adjustedIndex);
- }
-
- @Override public ReplicatedLogEntry last() {
- if (journal.size() == 0) {
- return null;
- }
- return get(journal.size() - 1);
- }
-
- @Override public long lastIndex() {
- if (journal.size() == 0) {
- return -1;
- }
-
- return last().getIndex();
- }
-
- @Override public long lastTerm() {
- if (journal.size() == 0) {
- return -1;
- }
-
- return last().getTerm();
+ super();
}
+ @Override public void removeFromAndPersist(long logEntryIndex) {
+ int adjustedIndex = adjustedIndex(logEntryIndex);
- @Override public void removeFrom(long index) {
- int adjustedIndex = adjustedIndex(index);
-
- if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
- return;
- }
-
- journal.subList(adjustedIndex , journal.size()).clear();
- }
-
-
- @Override public void removeFromAndPersist(long index) {
- int adjustedIndex = adjustedIndex(index);
-
- if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
+ if (adjustedIndex < 0) {
return;
}
@@ -417,29 +411,6 @@ public abstract class RaftActor extends UntypedPersistentActor {
//FIXME : Doing nothing for now
}
});
-
-
- }
-
- @Override public void append(
- final ReplicatedLogEntry replicatedLogEntry) {
- journal.add(replicatedLogEntry);
- }
-
- @Override public List getFrom(long index) {
- int adjustedIndex = adjustedIndex(index);
-
- List entries = new ArrayList<>(100);
- if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
- return entries;
- }
-
-
- for (int i = adjustedIndex;
- i < journal.size(); i++) {
- entries.add(journal.get(i));
- }
- return entries;
}
@Override public void appendAndPersist(
@@ -451,7 +422,7 @@ public abstract class RaftActor extends UntypedPersistentActor {
final String identifier,
final ReplicatedLogEntry replicatedLogEntry) {
context.getLogger().debug(
- "Append log entry and persist " + replicatedLogEntry);
+ "Append log entry and persist {} ", replicatedLogEntry);
// FIXME : By adding the replicated log entry to the in-memory journal we are not truly ensuring durability of the logs
journal.add(replicatedLogEntry);
@@ -464,20 +435,42 @@ public abstract class RaftActor extends UntypedPersistentActor {
new Procedure() {
public void apply(ReplicatedLogEntry evt) throws Exception {
// FIXME : Tentatively create a snapshot every hundred thousand entries. To be tuned.
- if (size() > 100000) {
- ReplicatedLogEntry lastAppliedEntry =
- get(context.getLastApplied());
+ if (journal.size() > context.getConfigParams().getSnapshotBatchCount()) {
+ LOG.info("Initiating Snapshot Capture..");
long lastAppliedIndex = -1;
long lastAppliedTerm = -1;
+
+ ReplicatedLogEntry lastAppliedEntry = get(context.getLastApplied());
if (lastAppliedEntry != null) {
lastAppliedIndex = lastAppliedEntry.getIndex();
lastAppliedTerm = lastAppliedEntry.getTerm();
}
- saveSnapshot(Snapshot.create(createSnapshot(),
+ LOG.debug("Snapshot Capture logSize: {}", journal.size());
+ LOG.debug("Snapshot Capture lastApplied:{} ", context.getLastApplied());
+ LOG.debug("Snapshot Capture lastAppliedIndex:{}", lastAppliedIndex);
+ LOG.debug("Snapshot Capture lastAppliedTerm:{}", lastAppliedTerm);
+
+ // create a snapshot object from the state provided and save it
+ // when snapshot is saved async, SaveSnapshotSuccess is raised.
+ Snapshot sn = Snapshot.create(createSnapshot(),
getFrom(context.getLastApplied() + 1),
lastIndex(), lastTerm(), lastAppliedIndex,
- lastAppliedTerm));
+ lastAppliedTerm);
+ saveSnapshot(sn);
+
+ LOG.info("Persisting of snapshot done:{}", sn.getLogMessage());
+
+ //be greedy and remove entries from in-mem journal which are in the snapshot
+ // and update snapshotIndex and snapshotTerm without waiting for the success,
+ // TODO: damage-recovery to be done on failure
+ journal.subList(0, (int) (lastAppliedIndex - snapshotIndex)).clear();
+ snapshotIndex = lastAppliedIndex;
+ snapshotTerm = lastAppliedTerm;
+
+ LOG.info("Removed in-memory snapshotted entries, " +
+ "adjusted snaphsotIndex:{}" +
+ "and term:{}", snapshotIndex, lastAppliedTerm);
}
// Send message for replication
if (clientActor != null) {
@@ -491,46 +484,8 @@ public abstract class RaftActor extends UntypedPersistentActor {
);
}
- @Override public long size() {
- return journal.size() + snapshotIndex + 1;
- }
-
- @Override public boolean isPresent(long index) {
- int adjustedIndex = adjustedIndex(index);
-
- if (adjustedIndex < 0 || adjustedIndex >= journal.size()) {
- return false;
- }
- return true;
- }
-
- @Override public boolean isInSnapshot(long index) {
- return index <= snapshotIndex;
- }
-
- @Override public Object getSnapshot() {
- return snapshot;
- }
-
- @Override public long getSnapshotIndex() {
- return snapshotIndex;
- }
-
- @Override public long getSnapshotTerm() {
- return snapshotTerm;
- }
-
- private int adjustedIndex(long index) {
- if(snapshotIndex < 0){
- return (int) index;
- }
- return (int) (index - snapshotIndex);
- }
}
-
-
-
private static class DeleteEntries implements Serializable {
private final int fromIndex;
@@ -591,6 +546,17 @@ public abstract class RaftActor extends UntypedPersistentActor {
public long getLastAppliedTerm() {
return lastAppliedTerm;
}
+
+ public String getLogMessage() {
+ StringBuilder sb = new StringBuilder();
+ return sb.append("Snapshot={")
+ .append("lastTerm:" + this.getLastTerm() + ", ")
+ .append("LastAppliedIndex:" + this.getLastAppliedIndex() + ", ")
+ .append("LastAppliedTerm:" + this.getLastAppliedTerm() + ", ")
+ .append("UnAppliedEntries size:" + this.getUnAppliedEntries().size() + "}")
+ .toString();
+
+ }
}
private class ElectionTermImpl implements ElectionTerm {
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java
index 7150ec0e6e..0eb4b73779 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java
@@ -85,6 +85,12 @@ public interface RaftActorContext {
*/
void setLastApplied(long lastApplied);
+ /**
+ *
+ * @param replicatedLog
+ */
+ public void setReplicatedLog(ReplicatedLog replicatedLog);
+
/**
* @return A representation of the log
*/
@@ -96,21 +102,27 @@ public interface RaftActorContext {
ActorSystem getActorSystem();
/**
+ * Get the logger to be used for logging messages
*
* @return
*/
LoggingAdapter getLogger();
/**
- * Get a mapping of peer id's their addresses
+ * Get a mapping of peerId's to their addresses
+ *
* @return
+ *
*/
Map getPeerAddresses();
/**
+ * Get the address of the peer as a String. This is the same format in
+ * which a consumer would provide the address
*
* @param peerId
- * @return
+ * @return The address of the peer or null if the address has not yet been
+ * resolved
*/
String getPeerAddress(String peerId);
@@ -126,4 +138,32 @@ public interface RaftActorContext {
* @param name
*/
public void removePeer(String name);
+
+ /**
+ * Given a peerId return the corresponding actor
+ *
+ *
+ *
+ * @param peerId
+ * @return The actorSelection corresponding to the peer or null if the
+ * address has not yet been resolved
+ */
+ ActorSelection getPeerActorSelection(String peerId);
+
+ /**
+ * Set Peer Address can be called at a later time to change the address of
+ * a known peer.
+ *
+ *
+ * Throws an IllegalStateException if the peer is unknown
+ *
+ * @param peerId
+ * @param peerAddress
+ */
+ void setPeerAddress(String peerId, String peerAddress);
+
+ /**
+ * @return ConfigParams
+ */
+ public ConfigParams getConfigParams();
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java
index a0f13280c2..25da37105c 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java
@@ -17,7 +17,9 @@ import akka.event.LoggingAdapter;
import java.util.Map;
-public class RaftActorContextImpl implements RaftActorContext{
+import static com.google.common.base.Preconditions.checkState;
+
+public class RaftActorContextImpl implements RaftActorContext {
private final ActorRef actor;
@@ -31,17 +33,20 @@ public class RaftActorContextImpl implements RaftActorContext{
private long lastApplied;
- private final ReplicatedLog replicatedLog;
+ private ReplicatedLog replicatedLog;
private final Map peerAddresses;
private final LoggingAdapter LOG;
+ private final ConfigParams configParams;
public RaftActorContextImpl(ActorRef actor, UntypedActorContext context,
String id,
ElectionTerm termInformation, long commitIndex,
- long lastApplied, ReplicatedLog replicatedLog, Map peerAddresses, LoggingAdapter logger) {
+ long lastApplied, ReplicatedLog replicatedLog,
+ Map peerAddresses, ConfigParams configParams,
+ LoggingAdapter logger) {
this.actor = actor;
this.context = context;
this.id = id;
@@ -50,6 +55,7 @@ public class RaftActorContextImpl implements RaftActorContext{
this.lastApplied = lastApplied;
this.replicatedLog = replicatedLog;
this.peerAddresses = peerAddresses;
+ this.configParams = configParams;
this.LOG = logger;
}
@@ -89,6 +95,10 @@ public class RaftActorContextImpl implements RaftActorContext{
this.lastApplied = lastApplied;
}
+ @Override public void setReplicatedLog(ReplicatedLog replicatedLog) {
+ this.replicatedLog = replicatedLog;
+ }
+
@Override public ReplicatedLog getReplicatedLog() {
return replicatedLog;
}
@@ -109,13 +119,30 @@ public class RaftActorContextImpl implements RaftActorContext{
return peerAddresses.get(peerId);
}
+ @Override public ConfigParams getConfigParams() {
+ return configParams;
+ }
+
@Override public void addToPeers(String name, String address) {
- LOG.debug("Kamal--> addToPeer for:"+name);
peerAddresses.put(name, address);
}
@Override public void removePeer(String name) {
- LOG.debug("Kamal--> removePeer for:"+name);
peerAddresses.remove(name);
}
+
+ @Override public ActorSelection getPeerActorSelection(String peerId) {
+ String peerAddress = getPeerAddress(peerId);
+ if(peerAddress != null){
+ return actorSelection(peerAddress);
+ }
+ return null;
+ }
+
+ @Override public void setPeerAddress(String peerId, String peerAddress) {
+ LOG.info("Peer address for peer {} set to {}", peerId, peerAddress);
+ checkState(peerAddresses.containsKey(peerId), peerId + " is unknown");
+
+ peerAddresses.put(peerId, peerAddress);
+ }
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ApplySnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplySnapshot.java
similarity index 89%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ApplySnapshot.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplySnapshot.java
index f9c7c133ee..9739fb2f1b 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ApplySnapshot.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplySnapshot.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ApplyState.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java
similarity index 94%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ApplyState.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java
index f58d74829a..b904335be3 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ApplyState.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ApplyState.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import akka.actor.ActorRef;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/CommitEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CommitEntry.java
similarity index 86%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/CommitEntry.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CommitEntry.java
index ba321c6c0e..07e376fca3 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/CommitEntry.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CommitEntry.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ElectionTimeout.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ElectionTimeout.java
similarity index 85%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ElectionTimeout.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ElectionTimeout.java
index 1c58f4bd31..a844849f15 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/ElectionTimeout.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/ElectionTimeout.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/PersistEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/PersistEntry.java
similarity index 87%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/PersistEntry.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/PersistEntry.java
index fe0dcc550b..6a62817e90 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/PersistEntry.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/PersistEntry.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/Replicate.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/Replicate.java
similarity index 94%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/Replicate.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/Replicate.java
index e9cdcf0b86..9bc737a0e3 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/Replicate.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/Replicate.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import akka.actor.ActorRef;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SaveSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SaveSnapshot.java
similarity index 88%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SaveSnapshot.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SaveSnapshot.java
index ce0ad1f501..861f5ee715 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SaveSnapshot.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SaveSnapshot.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SendHeartBeat.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendHeartBeat.java
similarity index 88%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SendHeartBeat.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendHeartBeat.java
index 1555766cdb..3c8c845f5d 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SendHeartBeat.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendHeartBeat.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SendInstallSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendInstallSnapshot.java
similarity index 85%
rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SendInstallSnapshot.java
rename to opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendInstallSnapshot.java
index b85e58b4f8..6c3313f316 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/internal/messages/SendInstallSnapshot.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/SendInstallSnapshot.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-package org.opendaylight.controller.cluster.raft.internal.messages;
+package org.opendaylight.controller.cluster.raft.base.messages;
import java.io.Serializable;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java
index bc87370b15..0a553b40fd 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java
@@ -15,8 +15,8 @@ import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
import org.opendaylight.controller.cluster.raft.SerializationUtils;
-import org.opendaylight.controller.cluster.raft.internal.messages.ApplyState;
-import org.opendaylight.controller.cluster.raft.internal.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.messages.RequestVote;
@@ -43,27 +43,6 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior {
*/
protected final RaftActorContext context;
- /**
- * The maximum election time variance
- */
- private static final int ELECTION_TIME_MAX_VARIANCE = 100;
-
- /**
- * The interval at which a heart beat message will be sent to the remote
- * RaftActor
- *
- * Since this is set to 100 milliseconds the Election timeout should be
- * at least 200 milliseconds
- */
- protected static final FiniteDuration HEART_BEAT_INTERVAL =
- new FiniteDuration(100, TimeUnit.MILLISECONDS);
-
- /**
- * The interval in which a new election would get triggered if no leader is found
- */
- private static final long ELECTION_TIME_INTERVAL =
- HEART_BEAT_INTERVAL.toMillis() * 2;
-
/**
*
*/
@@ -208,9 +187,9 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior {
* @return
*/
protected FiniteDuration electionDuration() {
- long variance = new Random().nextInt(ELECTION_TIME_MAX_VARIANCE);
- return new FiniteDuration(ELECTION_TIME_INTERVAL + variance,
- TimeUnit.MILLISECONDS);
+ long variance = new Random().nextInt(context.getConfigParams().getElectionTimeVariance());
+ return context.getConfigParams().getElectionTimeOutInterval().$plus(
+ new FiniteDuration(variance, TimeUnit.MILLISECONDS));
}
/**
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java
index ecd4901246..c125bd32b6 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java
@@ -12,16 +12,14 @@ import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
-import org.opendaylight.controller.cluster.raft.internal.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
import org.opendaylight.controller.cluster.raft.messages.RequestVote;
import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Set;
/**
* The behavior of a RaftActor when it is in the CandidateState
@@ -43,24 +41,20 @@ import java.util.Map;
*/
public class Candidate extends AbstractRaftActorBehavior {
- private final Map peerToActor = new HashMap<>();
-
private int voteCount;
private final int votesRequired;
+ private final Set peers;
+
public Candidate(RaftActorContext context) {
super(context);
- Collection peerPaths = context.getPeerAddresses().values();
+ peers = context.getPeerAddresses().keySet();
- for (String peerPath : peerPaths) {
- peerToActor.put(peerPath,
- context.actorSelection(peerPath));
- }
+ context.getLogger().debug("Election:Candidate has following peers:"+ peers);
- context.getLogger().debug("Election:Candidate has following peers:"+peerToActor.keySet());
- if(peerPaths.size() > 0) {
+ if(peers.size() > 0) {
// Votes are required from a majority of the peers including self.
// The votesRequired field therefore stores a calculated value
// of the number of votes required for this candidate to win an
@@ -73,7 +67,7 @@ public class Candidate extends AbstractRaftActorBehavior {
// 0 peers = 1 votesRequired (0 + 1) / 2 + 1 = 1
// 2 peers = 2 votesRequired (2 + 1) / 2 + 1 = 2
// 4 peers = 3 votesRequired (4 + 1) / 2 + 1 = 3
- int noOfPeers = peerPaths.size();
+ int noOfPeers = peers.size();
int self = 1;
votesRequired = (noOfPeers + self) / 2 + 1;
} else {
@@ -87,6 +81,8 @@ public class Candidate extends AbstractRaftActorBehavior {
@Override protected RaftState handleAppendEntries(ActorRef sender,
AppendEntries appendEntries) {
+ context.getLogger().info("Candidate: Received {}", appendEntries.toString());
+
return state();
}
@@ -115,10 +111,16 @@ public class Candidate extends AbstractRaftActorBehavior {
}
@Override
- public RaftState handleMessage(ActorRef sender, Object message) {
+ public RaftState handleMessage(ActorRef sender, Object originalMessage) {
+
+ Object message = fromSerializableMessage(originalMessage);
if (message instanceof RaftRPC) {
+
RaftRPC rpc = (RaftRPC) message;
+
+ context.getLogger().debug("RaftRPC message received {} my term is {}", rpc.toString(), context.getTermInformation().getCurrentTerm());
+
// If RPC request or response contains term T > currentTerm:
// set currentTerm = T, convert to follower (§5.1)
// This applies to all RPC messages and responses
@@ -141,6 +143,7 @@ public class Candidate extends AbstractRaftActorBehavior {
scheduleElection(electionDuration());
return state();
}
+
return super.handleMessage(sender, message);
}
@@ -153,21 +156,25 @@ public class Candidate extends AbstractRaftActorBehavior {
// Increment the election term and vote for self
long currentTerm = context.getTermInformation().getCurrentTerm();
- context.getTermInformation().updateAndPersist(currentTerm + 1, context.getId());
+ context.getTermInformation().updateAndPersist(currentTerm + 1,
+ context.getId());
- context.getLogger().debug("Starting new term " + (currentTerm+1));
+ context.getLogger().debug("Starting new term " + (currentTerm + 1));
// Request for a vote
// TODO: Retry request for vote if replies do not arrive in a reasonable
// amount of time TBD
- for (ActorSelection peerActor : peerToActor.values()) {
- peerActor.tell(new RequestVote(
- context.getTermInformation().getCurrentTerm(),
- context.getId(),
- context.getReplicatedLog().lastIndex(),
- context.getReplicatedLog().lastTerm()),
- context.getActor()
- );
+ for (String peerId : peers) {
+ ActorSelection peerActor = context.getPeerActorSelection(peerId);
+ if(peerActor != null) {
+ peerActor.tell(new RequestVote(
+ context.getTermInformation().getCurrentTerm(),
+ context.getId(),
+ context.getReplicatedLog().lastIndex(),
+ context.getReplicatedLog().lastTerm()),
+ context.getActor()
+ );
+ }
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java
index 68b444b2ba..c8cd41dfa1 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java
@@ -12,8 +12,8 @@ import akka.actor.ActorRef;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.internal.messages.ApplySnapshot;
-import org.opendaylight.controller.cluster.raft.internal.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
@@ -40,6 +40,11 @@ public class Follower extends AbstractRaftActorBehavior {
@Override protected RaftState handleAppendEntries(ActorRef sender,
AppendEntries appendEntries) {
+ if(appendEntries.getEntries() != null && appendEntries.getEntries().size() > 0) {
+ context.getLogger()
+ .info("Follower: Received {}", appendEntries.toString());
+ }
+
// TODO : Refactor this method into a bunch of smaller methods
// to make it easier to read. Before refactoring ensure tests
// cover the code properly
@@ -121,15 +126,10 @@ public class Follower extends AbstractRaftActorBehavior {
int addEntriesFrom = 0;
if (context.getReplicatedLog().size() > 0) {
- // Find the entry up until which the one that is not in the
- // follower's log
- for (int i = 0;
- i < appendEntries.getEntries()
- .size(); i++, addEntriesFrom++) {
- ReplicatedLogEntry matchEntry =
- appendEntries.getEntries().get(i);
- ReplicatedLogEntry newEntry = context.getReplicatedLog()
- .get(matchEntry.getIndex());
+ // Find the entry up until which the one that is not in the follower's log
+ for (int i = 0;i < appendEntries.getEntries().size(); i++, addEntriesFrom++) {
+ ReplicatedLogEntry matchEntry = appendEntries.getEntries().get(i);
+ ReplicatedLogEntry newEntry = context.getReplicatedLog().get(matchEntry.getIndex());
if (newEntry == null) {
//newEntry not found in the log
@@ -162,8 +162,9 @@ public class Follower extends AbstractRaftActorBehavior {
for (int i = addEntriesFrom;
i < appendEntries.getEntries().size(); i++) {
- context.getLogger().debug(
- "Append entry to log " + appendEntries.getEntries().get(i).getData()
+ context.getLogger().info(
+ "Append entry to log " + appendEntries.getEntries().get(
+ i).getData()
.toString()
);
context.getReplicatedLog()
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
index 26beed2f7a..2a44e8b7a5 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java
@@ -19,10 +19,10 @@ import org.opendaylight.controller.cluster.raft.FollowerLogInformationImpl;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.internal.messages.ApplyState;
-import org.opendaylight.controller.cluster.raft.internal.messages.Replicate;
-import org.opendaylight.controller.cluster.raft.internal.messages.SendHeartBeat;
-import org.opendaylight.controller.cluster.raft.internal.messages.SendInstallSnapshot;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.Replicate;
+import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
+import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
@@ -36,6 +36,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -67,7 +68,7 @@ public class Leader extends AbstractRaftActorBehavior {
private final Map followerToLog =
new HashMap();
- private final Map followerToActor = new HashMap<>();
+ private final Set followers;
private Cancellable heartbeatSchedule = null;
private Cancellable appendEntriesSchedule = null;
@@ -84,22 +85,21 @@ public class Leader extends AbstractRaftActorBehavior {
context.setCommitIndex(lastIndex());
}
- for (String followerId : context.getPeerAddresses().keySet()) {
+ followers = context.getPeerAddresses().keySet();
+
+ for (String followerId : followers) {
FollowerLogInformation followerLogInformation =
new FollowerLogInformationImpl(followerId,
new AtomicLong(lastIndex()),
new AtomicLong(-1));
- followerToActor.put(followerId,
- context.actorSelection(context.getPeerAddress(followerId)));
-
followerToLog.put(followerId, followerLogInformation);
}
- context.getLogger().debug("Election:Leader has following peers:"+followerToActor.keySet());
+ context.getLogger().debug("Election:Leader has following peers:"+ followers);
- if (followerToActor.size() > 0) {
- minReplicationCount = (followerToActor.size() + 1) / 2 + 1;
+ if (followers.size() > 0) {
+ minReplicationCount = (followers.size() + 1) / 2 + 1;
} else {
minReplicationCount = 0;
}
@@ -112,8 +112,8 @@ public class Leader extends AbstractRaftActorBehavior {
scheduleHeartBeat(new FiniteDuration(0, TimeUnit.SECONDS));
scheduleInstallSnapshotCheck(
- new FiniteDuration(HEART_BEAT_INTERVAL.length() * 1000,
- HEART_BEAT_INTERVAL.unit())
+ new FiniteDuration(context.getConfigParams().getHeartBeatInterval().length() * 1000,
+ context.getConfigParams().getHeartBeatInterval().unit())
);
}
@@ -121,16 +121,29 @@ public class Leader extends AbstractRaftActorBehavior {
@Override protected RaftState handleAppendEntries(ActorRef sender,
AppendEntries appendEntries) {
+ context.getLogger().info("Leader: Received {}", appendEntries.toString());
+
return state();
}
@Override protected RaftState handleAppendEntriesReply(ActorRef sender,
AppendEntriesReply appendEntriesReply) {
+ if(! appendEntriesReply.isSuccess()) {
+ context.getLogger()
+ .info("Leader: Received {}", appendEntriesReply.toString());
+ }
+
// Update the FollowerLogInformation
String followerId = appendEntriesReply.getFollowerId();
FollowerLogInformation followerLogInformation =
followerToLog.get(followerId);
+
+ if(followerLogInformation == null){
+ context.getLogger().error("Unknown follower {}", followerId);
+ return state();
+ }
+
if (appendEntriesReply.isSuccess()) {
followerLogInformation
.setMatchIndex(appendEntriesReply.getLogLastIndex());
@@ -228,7 +241,7 @@ public class Leader extends AbstractRaftActorBehavior {
(InstallSnapshotReply) message);
}
} finally {
- scheduleHeartBeat(HEART_BEAT_INTERVAL);
+ scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
}
return super.handleMessage(sender, message);
@@ -251,7 +264,7 @@ public class Leader extends AbstractRaftActorBehavior {
context.getLogger().debug("Replicate message " + logIndex);
- if (followerToActor.size() == 0) {
+ if (followers.size() == 0) {
context.setCommitIndex(
replicate.getReplicatedLogEntry().getIndex());
@@ -277,32 +290,37 @@ public class Leader extends AbstractRaftActorBehavior {
private void sendAppendEntries() {
// Send an AppendEntries to all followers
- for (String followerId : followerToActor.keySet()) {
+ for (String followerId : followers) {
ActorSelection followerActor =
- followerToActor.get(followerId);
+ context.getPeerActorSelection(followerId);
- FollowerLogInformation followerLogInformation =
- followerToLog.get(followerId);
+ if (followerActor != null) {
+ FollowerLogInformation followerLogInformation =
+ followerToLog.get(followerId);
- long nextIndex = followerLogInformation.getNextIndex().get();
+ long nextIndex = followerLogInformation.getNextIndex().get();
- List entries = Collections.emptyList();
+ List entries = Collections.emptyList();
- if(context.getReplicatedLog().isPresent(nextIndex)){
- // TODO: Instead of sending all entries from nextIndex
- // only send a fixed number of entries to each follower
- // This is to avoid the situation where there are a lot of
- // entries to install for a fresh follower or to a follower
- // that has fallen too far behind with the log but yet is not
- // eligible to receive a snapshot
- entries =
- context.getReplicatedLog().getFrom(nextIndex);
- }
+ if (context.getReplicatedLog().isPresent(nextIndex)) {
+ // TODO: Instead of sending all entries from nextIndex
+ // only send a fixed number of entries to each follower
+ // This is to avoid the situation where there are a lot of
+ // entries to install for a fresh follower or to a follower
+ // that has fallen too far behind with the log but yet is not
+ // eligible to receive a snapshot
+ entries =
+ context.getReplicatedLog().getFrom(nextIndex);
+ }
- followerActor.tell(
- new AppendEntries(currentTerm(), context.getId(), prevLogIndex(nextIndex),
- prevLogTerm(nextIndex), entries, context.getCommitIndex()).toSerializable(),
- actor());
+ followerActor.tell(
+ new AppendEntries(currentTerm(), context.getId(),
+ prevLogIndex(nextIndex),
+ prevLogTerm(nextIndex), entries,
+ context.getCommitIndex()).toSerializable(),
+ actor()
+ );
+ }
}
}
@@ -312,30 +330,33 @@ public class Leader extends AbstractRaftActorBehavior {
* snapshots at every heartbeat.
*/
private void installSnapshotIfNeeded(){
- for (String followerId : followerToActor.keySet()) {
+ for (String followerId : followers) {
ActorSelection followerActor =
- followerToActor.get(followerId);
-
- FollowerLogInformation followerLogInformation =
- followerToLog.get(followerId);
-
- long nextIndex = followerLogInformation.getNextIndex().get();
-
- if(!context.getReplicatedLog().isPresent(nextIndex) && context.getReplicatedLog().isInSnapshot(nextIndex)){
- followerActor.tell(
- new InstallSnapshot(currentTerm(), context.getId(),
- context.getReplicatedLog().getSnapshotIndex(),
- context.getReplicatedLog().getSnapshotTerm(),
- context.getReplicatedLog().getSnapshot()
- ),
- actor()
- );
+ context.getPeerActorSelection(followerId);
+
+ if(followerActor != null) {
+ FollowerLogInformation followerLogInformation =
+ followerToLog.get(followerId);
+
+ long nextIndex = followerLogInformation.getNextIndex().get();
+
+ if (!context.getReplicatedLog().isPresent(nextIndex) && context
+ .getReplicatedLog().isInSnapshot(nextIndex)) {
+ followerActor.tell(
+ new InstallSnapshot(currentTerm(), context.getId(),
+ context.getReplicatedLog().getSnapshotIndex(),
+ context.getReplicatedLog().getSnapshotTerm(),
+ context.getReplicatedLog().getSnapshot()
+ ),
+ actor()
+ );
+ }
}
}
}
private RaftState sendHeartBeat() {
- if (followerToActor.size() > 0) {
+ if (followers.size() > 0) {
sendAppendEntries();
}
return state();
@@ -354,7 +375,7 @@ public class Leader extends AbstractRaftActorBehavior {
}
private void scheduleHeartBeat(FiniteDuration interval) {
- if(followerToActor.keySet().size() == 0){
+ if(followers.size() == 0){
// Optimization - do not bother scheduling a heartbeat as there are
// no followers
return;
@@ -376,7 +397,7 @@ public class Leader extends AbstractRaftActorBehavior {
private void scheduleInstallSnapshotCheck(FiniteDuration interval) {
- if(followerToActor.keySet().size() == 0){
+ if(followers.size() == 0){
// Optimization - do not bother scheduling a heartbeat as there are
// no followers
return;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java
index 45ac9a9ebf..94366efd5e 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java
@@ -14,7 +14,6 @@ import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -24,7 +23,7 @@ import java.util.Map;
* Invoked by leader to replicate log entries (§5.3); also used as
* heartbeat (§5.2).
*/
-public class AppendEntries extends AbstractRaftRPC implements Serializable {
+public class AppendEntries extends AbstractRaftRPC {
public static final Class SERIALIZABLE_CLASS = AppendEntriesMessages.AppendEntries.class;
@@ -77,13 +76,16 @@ public class AppendEntries extends AbstractRaftRPC implements Serializable {
}
@Override public String toString() {
- return "AppendEntries{" +
- "leaderId='" + leaderId + '\'' +
- ", prevLogIndex=" + prevLogIndex +
- ", prevLogTerm=" + prevLogTerm +
- ", entries=" + entries +
- ", leaderCommit=" + leaderCommit +
- '}';
+ final StringBuilder sb =
+ new StringBuilder("AppendEntries{");
+ sb.append("term=").append(getTerm());
+ sb.append("leaderId='").append(leaderId).append('\'');
+ sb.append(", prevLogIndex=").append(prevLogIndex);
+ sb.append(", prevLogTerm=").append(prevLogTerm);
+ sb.append(", entries=").append(entries);
+ sb.append(", leaderCommit=").append(leaderCommit);
+ sb.append('}');
+ return sb.toString();
}
public Object toSerializable(){
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java
index 7e6628abe1..b923baa716 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java
@@ -8,12 +8,10 @@
package org.opendaylight.controller.cluster.raft.messages;
-import java.io.Serializable;
-
/**
* Reply for the AppendEntriesRpc message
*/
-public class AppendEntriesReply extends AbstractRaftRPC implements Serializable {
+public class AppendEntriesReply extends AbstractRaftRPC {
// true if follower contained entry matching
// prevLogIndex and prevLogTerm
@@ -58,4 +56,16 @@ public class AppendEntriesReply extends AbstractRaftRPC implements Serializable
public String getFollowerId() {
return followerId;
}
+
+ @Override public String toString() {
+ final StringBuilder sb =
+ new StringBuilder("AppendEntriesReply{");
+ sb.append("term=").append(term);
+ sb.append(", success=").append(success);
+ sb.append(", logLastIndex=").append(logLastIndex);
+ sb.append(", logLastTerm=").append(logLastTerm);
+ sb.append(", followerId='").append(followerId).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java
index 5053560b41..888854fa71 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java
@@ -8,9 +8,7 @@
package org.opendaylight.controller.cluster.raft.messages;
-import java.io.Serializable;
-
-public class InstallSnapshot extends AbstractRaftRPC implements Serializable {
+public class InstallSnapshot extends AbstractRaftRPC {
private final String leaderId;
private final long lastIncludedIndex;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java
index 02a3252776..85b89b70ae 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java
@@ -8,9 +8,7 @@
package org.opendaylight.controller.cluster.raft.messages;
-import java.io.Serializable;
-
-public class InstallSnapshotReply extends AbstractRaftRPC implements Serializable {
+public class InstallSnapshotReply extends AbstractRaftRPC {
// The followerId - this will be used to figure out which follower is
// responding
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RaftRPC.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RaftRPC.java
index a770e54f58..10d99988d8 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RaftRPC.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RaftRPC.java
@@ -8,6 +8,8 @@
package org.opendaylight.controller.cluster.raft.messages;
-public interface RaftRPC {
+import java.io.Serializable;
+
+public interface RaftRPC extends Serializable {
public long getTerm();
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java
index 310968de95..6ef2a06285 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java
@@ -8,12 +8,10 @@
package org.opendaylight.controller.cluster.raft.messages;
-import java.io.Serializable;
-
/**
* Invoked by candidates to gather votes (§5.2).
*/
-public class RequestVote extends AbstractRaftRPC implements Serializable{
+public class RequestVote extends AbstractRaftRPC {
// candidate requesting vote
private String candidateId;
@@ -63,4 +61,15 @@ public class RequestVote extends AbstractRaftRPC implements Serializable{
public void setLastLogTerm(long lastLogTerm) {
this.lastLogTerm = lastLogTerm;
}
+
+ @Override public String toString() {
+ final StringBuilder sb =
+ new StringBuilder("RequestVote{");
+ sb.append("term='").append(getTerm()).append('\'');
+ sb.append("candidateId='").append(candidateId).append('\'');
+ sb.append(", lastLogIndex=").append(lastLogIndex);
+ sb.append(", lastLogTerm=").append(lastLogTerm);
+ sb.append('}');
+ return sb.toString();
+ }
}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java
index a658ab7d81..df80b4e5e2 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java
@@ -8,9 +8,7 @@
package org.opendaylight.controller.cluster.raft.messages;
-import java.io.Serializable;
-
-public class RequestVoteReply extends AbstractRaftRPC implements Serializable {
+public class RequestVoteReply extends AbstractRaftRPC {
// true means candidate received vot
private final boolean voteGranted;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java
new file mode 100644
index 0000000000..ae8e525233
--- /dev/null
+++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.raft;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import static org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
+/**
+*
+*/
+public class AbstractReplicatedLogImplTest {
+
+ private MockAbstractReplicatedLogImpl replicatedLogImpl;
+
+ @Before
+ public void setUp() {
+ replicatedLogImpl = new MockAbstractReplicatedLogImpl();
+ }
+
+ @After
+ public void tearDown() {
+ replicatedLogImpl.journal.clear();
+ replicatedLogImpl.setSnapshotIndex(-1);
+ replicatedLogImpl.setSnapshotTerm(-1);
+ replicatedLogImpl = null;
+ }
+
+ @Test
+ public void testIndexOperations() {
+ // create a set of initial entries in the in-memory log
+ replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
+
+ // check if the values returned are correct, with snapshotIndex = -1
+ assertEquals("B", replicatedLogImpl.get(1).getData().toString());
+ assertEquals("D", replicatedLogImpl.last().getData().toString());
+ assertEquals(3, replicatedLogImpl.lastIndex());
+ assertEquals(2, replicatedLogImpl.lastTerm());
+ assertEquals(2, replicatedLogImpl.getFrom(2).size());
+ assertEquals(4, replicatedLogImpl.size());
+ assertTrue(replicatedLogImpl.isPresent(2));
+ assertFalse(replicatedLogImpl.isPresent(4));
+ assertFalse(replicatedLogImpl.isInSnapshot(2));
+
+ // now create a snapshot of 3 entries, with 1 unapplied entry left in the log
+ // It removes the entries which have made it to snapshot
+ // and updates the snapshot index and term
+ Map state = takeSnapshot(3);
+
+ // check the values after the snapshot.
+ // each index value passed in the test is the logical index (log entry index)
+ // which gets mapped to the list's physical index
+ assertEquals("D", replicatedLogImpl.get(3).getData().toString());
+ assertEquals("D", replicatedLogImpl.last().getData().toString());
+ assertNull(replicatedLogImpl.get(1));
+ assertEquals(3, replicatedLogImpl.lastIndex());
+ assertEquals(2, replicatedLogImpl.lastTerm());
+ assertEquals(0, replicatedLogImpl.getFrom(2).size());
+ assertEquals(1, replicatedLogImpl.size());
+ assertFalse(replicatedLogImpl.isPresent(2));
+ assertTrue(replicatedLogImpl.isPresent(3));
+ assertFalse(replicatedLogImpl.isPresent(4));
+ assertTrue(replicatedLogImpl.isInSnapshot(2));
+
+ // append few more entries
+ replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("E")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("F")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(3, 6, new MockPayload("G")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(3, 7, new MockPayload("H")));
+
+ // check their values as well
+ assertEquals(5, replicatedLogImpl.size());
+ assertEquals("D", replicatedLogImpl.get(3).getData().toString());
+ assertEquals("E", replicatedLogImpl.get(4).getData().toString());
+ assertEquals("H", replicatedLogImpl.last().getData().toString());
+ assertEquals(3, replicatedLogImpl.lastTerm());
+ assertEquals(7, replicatedLogImpl.lastIndex());
+ assertTrue(replicatedLogImpl.isPresent(7));
+ assertFalse(replicatedLogImpl.isInSnapshot(7));
+ assertEquals(1, replicatedLogImpl.getFrom(7).size());
+ assertEquals(2, replicatedLogImpl.getFrom(6).size());
+
+ // take a second snapshot with 5 entries with 0 unapplied entries left in the log
+ state = takeSnapshot(5);
+
+ assertEquals(0, replicatedLogImpl.size());
+ assertNull(replicatedLogImpl.last());
+ assertNull(replicatedLogImpl.get(7));
+ assertNull(replicatedLogImpl.get(1));
+ assertFalse(replicatedLogImpl.isPresent(7));
+ assertTrue(replicatedLogImpl.isInSnapshot(7));
+ assertEquals(0, replicatedLogImpl.getFrom(7).size());
+ assertEquals(0, replicatedLogImpl.getFrom(6).size());
+
+ }
+
+ // create a snapshot for test
+ public Map takeSnapshot(int numEntries) {
+ Map map = new HashMap(numEntries);
+ List entries = replicatedLogImpl.getEntriesTill(numEntries);
+ for (ReplicatedLogEntry entry : entries) {
+ map.put(entry.getIndex(), entry.getData().toString());
+ }
+
+ int term = (int) replicatedLogImpl.lastTerm();
+ int lastIndex = (int) entries.get(entries.size() - 1).getIndex();
+ entries.clear();
+ replicatedLogImpl.setSnapshotTerm(term);
+ replicatedLogImpl.setSnapshotIndex(lastIndex);
+
+ return map;
+
+ }
+ class MockAbstractReplicatedLogImpl extends AbstractReplicatedLogImpl {
+ @Override
+ public void appendAndPersist(ReplicatedLogEntry replicatedLogEntry) {
+ }
+
+ @Override
+ public void removeFromAndPersist(long index) {
+ }
+
+ public void setSnapshotIndex(long snapshotIndex) {
+ this.snapshotIndex = snapshotIndex;
+ }
+
+ public void setSnapshotTerm(long snapshotTerm) {
+ this.snapshotTerm = snapshotTerm;
+ }
+
+ public List getEntriesTill(int index) {
+ return journal.subList(0, index);
+ }
+ }
+}
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
index 406c164cdb..aa50fa7442 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/MockRaftActorContext.java
@@ -18,6 +18,7 @@ import com.google.protobuf.GeneratedMessage;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
import org.opendaylight.controller.cluster.raft.protobuff.messages.MockPayloadMessages;
+import com.google.common.base.Preconditions;
import java.io.Serializable;
import java.util.ArrayList;
@@ -159,11 +160,27 @@ public class MockRaftActorContext implements RaftActorContext {
peerAddresses.remove(name);
}
+ @Override public ActorSelection getPeerActorSelection(String peerId) {
+ String peerAddress = getPeerAddress(peerId);
+ if(peerAddress != null){
+ return actorSelection(peerAddress);
+ }
+ return null;
+ }
+
+ @Override public void setPeerAddress(String peerId, String peerAddress) {
+ Preconditions.checkState(peerAddresses.containsKey(peerId));
+ peerAddresses.put(peerId, peerAddress);
+ }
+
public void setPeerAddresses(Map peerAddresses) {
this.peerAddresses = peerAddresses;
}
-
+ @Override
+ public ConfigParams getConfigParams() {
+ return new DefaultConfigParamsImpl();
+ }
public static class SimpleReplicatedLog implements ReplicatedLog {
private final List log = new ArrayList<>();
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
index 8bcee58afe..c763683705 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
@@ -9,7 +9,7 @@ import org.junit.Test;
import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
-import org.opendaylight.controller.cluster.raft.internal.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.messages.RequestVote;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
index 126e7d10c2..c015d950c4 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
@@ -9,7 +9,7 @@ import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.internal.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.messages.RequestVote;
diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java
index bc9d4a2767..d33b33925b 100644
--- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java
+++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java
@@ -8,9 +8,9 @@ import org.junit.Test;
import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
-import org.opendaylight.controller.cluster.raft.internal.messages.ApplyState;
-import org.opendaylight.controller.cluster.raft.internal.messages.Replicate;
-import org.opendaylight.controller.cluster.raft.internal.messages.SendHeartBeat;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.Replicate;
+import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java
index 823a4d9f32..b0c2d742e2 100644
--- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java
+++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java
@@ -23,7 +23,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
@@ -74,7 +74,7 @@ public final class RuntimeMappingModule extends
}
final RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(SingletonHolder.CLASS_POOL);
- bundleContext.registerService(SchemaServiceListener.class, service, new Hashtable());
+ bundleContext.registerService(SchemaContextListener.class, service, new Hashtable());
return service;
}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
index 15e4a466cf..2d81b6022d 100644
--- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
+++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
@@ -41,7 +41,6 @@ import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMapping
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,14 +57,14 @@ public abstract class AbstractForwardedDataBroker implements Delegator schemaListenerRegistration;
+ private final ListenerRegistration schemaListenerRegistration;
protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
final BindingIndependentMappingService mappingService,final SchemaService schemaService) {
this.domDataBroker = domDataBroker;
this.mappingService = mappingService;
this.codec = new BindingToNormalizedNodeCodec(mappingService);
- this.schemaListenerRegistration = schemaService.registerSchemaServiceListener(this);
+ this.schemaListenerRegistration = schemaService.registerSchemaContextListener(this);
}
protected BindingToNormalizedNodeCodec getCodec() {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.java
index df09f78620..05651bfabe 100644
--- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.java
+++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.java
@@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.binding.impl;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executors;
import org.opendaylight.controller.md.sal.binding.util.AbstractBindingSalProviderInstance;
import org.opendaylight.controller.sal.binding.api.mount.MountProviderInstance;
@@ -20,6 +21,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
public class MountPointManagerImpl implements MountProviderService {
@@ -82,7 +84,7 @@ public class MountPointManagerImpl implements MountProviderService {
RpcProviderRegistryImpl rpcRegistry = new RpcProviderRegistryImpl("mount");
NotificationBrokerImpl notificationBroker = new NotificationBrokerImpl(getNotificationExecutor());
DataBrokerImpl dataBroker = new DataBrokerImpl();
- dataBroker.setExecutor(getDataCommitExecutor());
+ dataBroker.setExecutor(MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
BindingMountPointImpl mountInstance = new BindingMountPointImpl(path, rpcRegistry, notificationBroker,
dataBroker);
mountPoints.putIfAbsent(path, mountInstance);
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java
new file mode 100644
index 0000000000..60d56db581
--- /dev/null
+++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014 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.controller.md.sal.binding.impl.test;
+
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertNotContains;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.USES_ONE_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.USES_TWO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ * This testsuite tries to replicate bug 1333 and tests regresion of it
+ * using test-model with similar construction as one reported.
+ *
+ *
+ * See https://bugs.opendaylight.org/show_bug.cgi?id=1333 for Bug Description
+ *
+ */
+public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTest{
+
+ private static final InstanceIdentifier TOP_PATH = InstanceIdentifier.create(Top.class);
+
+ private static final InstanceIdentifier> AUGMENT_WILDCARD = TOP_PATH.child(TopLevelList.class).augmentation(
+ TreeComplexUsesAugment.class);
+
+ public void writeTopWithListItem(final LogicalDatastoreType store) {
+ ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+ Top topItem = top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
+ tx.put(store, TOP_PATH, topItem);
+ assertCommit(tx.submit());
+ }
+
+ public void deleteItem(final LogicalDatastoreType store, final InstanceIdentifier> path) {
+ ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+ tx.delete(store, path);
+ assertCommit(tx.submit());
+ }
+
+ @Test
+ public void writeTopWithListItemAugmentedListenTopSubtree() {
+ TestListener listener = createListener(CONFIGURATION,TOP_PATH, DataChangeScope.SUBTREE);
+ listener.startCapture();
+
+ writeTopWithListItem(CONFIGURATION);
+
+ AsyncDataChangeEvent, DataObject> event = listener.event();
+
+ assertContains(event.getCreatedData(), TOP_PATH);
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY));
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_ONE_KEY));
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+
+ assertEmpty(event.getUpdatedData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void writeTopWithListItemAugmentedListenAugmentSubtreeWildcarded() {
+ TestListener listener = createListener(CONFIGURATION,AUGMENT_WILDCARD, DataChangeScope.SUBTREE);
+ listener.startCapture();
+ writeTopWithListItem(CONFIGURATION);
+
+ AsyncDataChangeEvent, DataObject> event = listener.event();
+
+ /*
+ * Event should not contain parent nodes
+ */
+ assertNotContains(event.getCreatedData(), TOP_PATH, path(TOP_FOO_KEY));
+
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_ONE_KEY));
+ assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+
+ assertEmpty(event.getUpdatedData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void deleteAugmentChildListenTopSubtree() {
+ writeTopWithListItem(CONFIGURATION);
+ TestListener listener = createListener(CONFIGURATION, TOP_PATH, DataChangeScope.SUBTREE);
+ InstanceIdentifier> deletePath = path(TOP_FOO_KEY,USES_ONE_KEY);
+ deleteItem(CONFIGURATION,deletePath);
+
+ AsyncDataChangeEvent, DataObject> event = listener.event();
+
+
+ assertEmpty(event.getCreatedData());
+
+ assertContains(event.getRemovedPaths(), deletePath);
+
+ assertContains(event.getUpdatedData(), TOP_PATH);
+ assertContains(event.getUpdatedData(), path(TOP_FOO_KEY));
+ assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+
+ assertNotContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+ }
+
+ @Test
+ public void deleteAugmentChildListenAugmentSubtreeWildcarded() {
+ writeTopWithListItem(CONFIGURATION);
+
+ TestListener listener = createListener(CONFIGURATION, AUGMENT_WILDCARD, DataChangeScope.SUBTREE);
+ InstanceIdentifier> deletePath = path(TOP_FOO_KEY,USES_ONE_KEY);
+ deleteItem(CONFIGURATION,deletePath);
+ AsyncDataChangeEvent, DataObject> event = listener.event();
+
+ assertEmpty(event.getCreatedData());
+
+ assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+
+ /*
+ * Event should not contain parent nodes
+ */
+ assertNotContains(event.getUpdatedData(), TOP_PATH, path(TOP_FOO_KEY));
+
+ assertContains(event.getRemovedPaths(), deletePath);
+ }
+
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
index 79aa6b634b..e0f6f3546f 100644
--- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
+++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
@@ -47,13 +47,13 @@ public class DataBrokerTestCustomizer {
public DOMStore createConfigurationDatastore() {
InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", MoreExecutors.sameThreadExecutor());
- schemaService.registerSchemaServiceListener(store);
+ schemaService.registerSchemaContextListener(store);
return store;
}
public DOMStore createOperationalDatastore() {
InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", MoreExecutors.sameThreadExecutor());
- schemaService.registerSchemaServiceListener(store);
+ schemaService.registerSchemaContextListener(store);
return store;
}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
index e82c9d385d..deb4a8aeca 100644
--- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
+++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
@@ -144,8 +144,8 @@ public class BindingTestContext implements AutoCloseable {
biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker,mockSchemaService);
- mockSchemaService.registerSchemaServiceListener(configStore);
- mockSchemaService.registerSchemaServiceListener(operStore);
+ mockSchemaService.registerSchemaContextListener(configStore);
+ mockSchemaService.registerSchemaContextListener(operStore);
biDataLegacyBroker = biCompatibleBroker;
}
@@ -246,7 +246,7 @@ public class BindingTestContext implements AutoCloseable {
public void startBindingToDomMappingService() {
checkState(classPool != null, "ClassPool needs to be present");
mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
- mockSchemaService.registerSchemaServiceListener(mappingServiceImpl);
+ mockSchemaService.registerSchemaContextListener(mappingServiceImpl);
}
private void updateYangSchema(final ImmutableSet moduleInfos) {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java
index c8acbcd994..63a4ffb23a 100644
--- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java
+++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/MockSchemaService.java
@@ -13,14 +13,14 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
@SuppressWarnings("deprecation")
public final class MockSchemaService implements SchemaService, SchemaContextProvider {
private SchemaContext schemaContext;
- ListenerRegistry listeners = ListenerRegistry.create();
+ ListenerRegistry listeners = ListenerRegistry.create();
@Override
public void addModule(final Module module) {
@@ -38,8 +38,8 @@ public final class MockSchemaService implements SchemaService, SchemaContextProv
}
@Override
- public ListenerRegistration registerSchemaServiceListener(
- final SchemaServiceListener listener) {
+ public ListenerRegistration registerSchemaContextListener(
+ final SchemaContextListener listener) {
return listeners.register(listener);
}
@@ -55,8 +55,8 @@ public final class MockSchemaService implements SchemaService, SchemaContextProv
public synchronized void changeSchema(final SchemaContext newContext) {
schemaContext = newContext;
- for (ListenerRegistration listener : listeners) {
+ for (ListenerRegistration listener : listeners) {
listener.getInstance().onGlobalContextUpdated(schemaContext);
}
}
-}
\ No newline at end of file
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/pom.xml b/opendaylight/md-sal/sal-distributed-datastore/pom.xml
index 16b97b7855..94c895dab3 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/pom.xml
+++ b/opendaylight/md-sal/sal-distributed-datastore/pom.xml
@@ -124,6 +124,12 @@
1.1-SNAPSHOT
+
+ org.opendaylight.controller
+ sal-akka-raft
+ 1.1-SNAPSHOT
+
+
junit
@@ -160,6 +166,7 @@
!*snappy;!org.jboss.*;*
sal-protocolbuffer-encoding;
+ sal-akka-raft;
!sal*;
!*config-api*;
!*testkit*;
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayload.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayload.java
new file mode 100644
index 0000000000..955e4bbf22
--- /dev/null
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/CompositeModificationPayload.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.datastore;
+
+import com.google.common.base.Preconditions;
+import com.google.protobuf.GeneratedMessage;
+import org.opendaylight.controller.cluster.example.protobuff.messages.KeyValueMessages;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages;
+import org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+public class CompositeModificationPayload extends Payload implements
+ Serializable {
+
+ private final PersistentMessages.CompositeModification modification;
+
+ public CompositeModificationPayload(){
+ modification = null;
+ }
+ public CompositeModificationPayload(Object modification){
+ this.modification = (PersistentMessages.CompositeModification) modification;
+ }
+
+ @Override public Map encode() {
+ Preconditions.checkState(modification!=null);
+ Map map = new HashMap<>();
+ map.put(org.opendaylight.controller.mdsal.CompositeModificationPayload.modification, this.modification);
+ return map;
+ }
+
+ @Override public Payload decode(
+ AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload payload) {
+ PersistentMessages.CompositeModification modification = payload
+ .getExtension(
+ org.opendaylight.controller.mdsal.CompositeModificationPayload.modification);
+ payload.getExtension(KeyValueMessages.value);
+ return new CompositeModificationPayload(modification);
+ }
+
+ public Object getModification(){
+ return this.modification;
+ }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java
index a67f58c760..34239070a3 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Configuration.java
@@ -15,9 +15,41 @@ import java.util.List;
import java.util.Map;
public interface Configuration {
+
+ /**
+ * Given a memberName find all the shards that belong on that member and
+ * return the names of those shards
+ *
+ * @param memberName
+ * @return
+ */
List getMemberShardNames(String memberName);
+
+ /**
+ * Given a module namespace return the name of a module
+ * @param nameSpace
+ * @return
+ */
Optional getModuleNameFromNameSpace(String nameSpace);
+
+ /**
+ * Get a mapping of the module names to it's corresponding ShardStrategy
+ * @return
+ */
Map getModuleNameToShardStrategyMap();
+
+ /**
+ * Given a module name find all the shardNames corresponding to it
+ * @param moduleName
+ * @return
+ */
List getShardNamesFromModuleName(String moduleName);
+
+ /**
+ * Given a shardName find all the members on which it belongs
+ *
+ * @param shardName
+ * @return
+ */
List getMembersFromShardName(String shardName);
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java
index 692d1b4954..6d87271f00 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreFactory.java
@@ -20,7 +20,7 @@ public class DistributedDataStoreFactory {
new DistributedDataStore(actorSystem, name, new ClusterWrapperImpl(actorSystem),config );
ShardStrategyFactory.setConfiguration(config);
schemaService
- .registerSchemaServiceListener(dataStore);
+ .registerSchemaContextListener(dataStore);
return dataStore;
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/NoOpCohort.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/NoOpCohort.java
new file mode 100644
index 0000000000..eb28159025
--- /dev/null
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/NoOpCohort.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.datastore;
+
+import akka.actor.UntypedActor;
+import org.opendaylight.controller.cluster.datastore.messages.AbortTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.AbortTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.CommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CommitTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.PreCommitTransactionReply;
+
+public class NoOpCohort extends UntypedActor {
+
+ @Override public void onReceive(Object message) throws Exception {
+ if (message.getClass().equals(CanCommitTransaction.SERIALIZABLE_CLASS)) {
+ getSender().tell(new CanCommitTransactionReply(false).toSerializable(), getSelf());
+ } else if (message.getClass().equals(PreCommitTransaction.SERIALIZABLE_CLASS)) {
+ getSender().tell(
+ new PreCommitTransactionReply().toSerializable(),
+ getSelf());
+ } else if (message.getClass().equals(CommitTransaction.SERIALIZABLE_CLASS)) {
+ getSender().tell(new CommitTransactionReply().toSerializable(), getSelf());
+ } else if (message.getClass().equals(AbortTransaction.SERIALIZABLE_CLASS)) {
+ getSender().tell(new AbortTransactionReply().toSerializable(), getSelf());
+ } else {
+ throw new Exception ("Not recognized message received,message="+message);
+ }
+
+ }
+}
+
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
index d6ad553cf3..999d0f8baf 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
@@ -14,9 +14,7 @@ import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.Creator;
-import akka.persistence.Persistent;
-import akka.persistence.RecoveryCompleted;
-import akka.persistence.UntypedProcessor;
+import akka.serialization.Serialization;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
@@ -28,12 +26,13 @@ import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionC
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
import org.opendaylight.controller.cluster.datastore.messages.ForwardedCommitTransaction;
-import org.opendaylight.controller.cluster.datastore.messages.NonPersistent;
+import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
import org.opendaylight.controller.cluster.datastore.modification.Modification;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.raft.RaftActor;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
@@ -54,7 +53,7 @@ import java.util.concurrent.Executors;
* Our Shard uses InMemoryDataStore as it's internal representation and delegates all requests it
*
*/
-public class Shard extends UntypedProcessor {
+public class Shard extends RaftActor {
public static final String DEFAULT_NAME = "default";
@@ -73,11 +72,16 @@ public class Shard extends UntypedProcessor {
// property persistent
private final boolean persistent;
+ private final String name;
+
private SchemaContext schemaContext;
private final ShardStats shardMBean;
- private Shard(String name) {
+ private Shard(String name, Map peerAddresses) {
+ super(name, peerAddresses);
+
+ this.name = name;
String setting = System.getProperty("shard.persistent");
@@ -91,78 +95,88 @@ public class Shard extends UntypedProcessor {
}
- public static Props props(final String name) {
+ public static Props props(final String name, final Map peerAddresses) {
return Props.create(new Creator() {
@Override
public Shard create() throws Exception {
- return new Shard(name);
+ return new Shard(name, peerAddresses);
}
});
}
- @Override
- public void onReceive(Object message) throws Exception {
- LOG.debug("Received message " + message.getClass().toString());
-
- if(!recoveryFinished()){
- // FIXME : Properly handle recovery
- return;
- }
+ @Override public void onReceiveCommand(Object message){
+ LOG.debug("Received message {} from {}", message.getClass().toString(), getSender());
if (message.getClass().equals(CreateTransactionChain.SERIALIZABLE_CLASS)) {
- createTransactionChain();
+ if(isLeader()) {
+ createTransactionChain();
+ } else if(getLeader() != null){
+ getLeader().forward(message, getContext());
+ }
} else if (message.getClass().equals(RegisterChangeListener.SERIALIZABLE_CLASS)) {
registerChangeListener(RegisterChangeListener.fromSerializable(getContext().system(), message));
} else if (message instanceof UpdateSchemaContext) {
updateSchemaContext((UpdateSchemaContext) message);
} else if (message instanceof ForwardedCommitTransaction) {
handleForwardedCommit((ForwardedCommitTransaction) message);
- } else if (message instanceof Persistent) {
- commit(((Persistent)message).payload());
} else if (message.getClass().equals(CreateTransaction.SERIALIZABLE_CLASS)) {
- createTransaction(CreateTransaction.fromSerializable(message));
- } else if(message instanceof NonPersistent){
- commit(((NonPersistent)message).payload());
- }else if (message instanceof RecoveryCompleted) {
- //FIXME: PROPERLY HANDLE RECOVERY COMPLETED
-
- }else {
- throw new Exception("Not recognized message found message=" + message);
+ if(isLeader()) {
+ createTransaction(CreateTransaction.fromSerializable(message));
+ } else if(getLeader() != null){
+ getLeader().forward(message, getContext());
+ }
+ } else if (message instanceof PeerAddressResolved){
+ PeerAddressResolved resolved = (PeerAddressResolved) message;
+ setPeerAddress(resolved.getPeerId(), resolved.getPeerAddress());
+ } else {
+ super.onReceiveCommand(message);
}
}
private void createTransaction(CreateTransaction createTransaction) {
DOMStoreReadWriteTransaction transaction =
store.newReadWriteTransaction();
+ String transactionId = "shard-" + createTransaction.getTransactionId();
+ LOG.info("Creating transaction : {} " , transactionId);
ActorRef transactionActor = getContext().actorOf(
- ShardTransaction.props(transaction, getSelf(), schemaContext), "shard-" + createTransaction.getTransactionId());
+ ShardTransaction.props(transaction, getSelf(), schemaContext), transactionId);
+
getSender()
- .tell(new CreateTransactionReply(transactionActor.path().toString(), createTransaction.getTransactionId()).toSerializable(),
+ .tell(new CreateTransactionReply(Serialization.serializedActorPath(transactionActor), createTransaction.getTransactionId()).toSerializable(),
getSelf());
}
- private void commit(Object serialized) {
+ private void commit(final ActorRef sender, Object serialized) {
Modification modification = MutableCompositeModification.fromSerializable(serialized, schemaContext);
DOMStoreThreePhaseCommitCohort cohort =
modificationToCohort.remove(serialized);
if (cohort == null) {
LOG.error(
"Could not find cohort for modification : " + modification);
+ LOG.info("Writing modification using a new transaction");
+ modification.apply(store.newReadWriteTransaction());
return;
}
+
final ListenableFuture future = cohort.commit();
shardMBean.incrementCommittedTransactionCount();
- final ActorRef sender = getSender();
final ActorRef self = getSelf();
future.addListener(new Runnable() {
@Override
public void run() {
try {
future.get();
- sender.tell(new CommitTransactionReply().toSerializable(), self);
+
+ if(sender != null) {
+ sender
+ .tell(new CommitTransactionReply().toSerializable(),
+ self);
+ } else {
+ LOG.error("sender is null ???");
+ }
} catch (InterruptedException | ExecutionException e) {
// FIXME : Handle this properly
LOG.error(e, "An exception happened when committing");
@@ -176,12 +190,11 @@ public class Shard extends UntypedProcessor {
modificationToCohort
.put(serializedModification , message.getCohort());
+
if(persistent) {
- getSelf().forward(Persistent.create(serializedModification),
- getContext());
+ this.persistData(getSender(), "identifier", new CompositeModificationPayload(serializedModification));
} else {
- getSelf().forward(NonPersistent.create(serializedModification),
- getContext());
+ this.commit(getSender(), serializedModification);
}
}
@@ -197,7 +210,8 @@ public class Shard extends UntypedProcessor {
ActorSelection dataChangeListenerPath = getContext()
- .system().actorSelection(registerChangeListener.getDataChangeListenerPath());
+ .system().actorSelection(
+ registerChangeListener.getDataChangeListenerPath());
AsyncDataChangeListener>
listener = new DataChangeListenerProxy(schemaContext,dataChangeListenerPath);
@@ -220,9 +234,36 @@ public class Shard extends UntypedProcessor {
private void createTransactionChain() {
DOMStoreTransactionChain chain = store.createTransactionChain();
ActorRef transactionChain =
- getContext().actorOf(ShardTransactionChain.props(chain, schemaContext));
+ getContext().actorOf(
+ ShardTransactionChain.props(chain, schemaContext));
getSender()
- .tell(new CreateTransactionChainReply(transactionChain.path()).toSerializable(),
+ .tell(new CreateTransactionChainReply(transactionChain.path())
+ .toSerializable(),
getSelf());
}
+
+ @Override protected void applyState(ActorRef clientActor, String identifier,
+ Object data) {
+
+ if(data instanceof CompositeModificationPayload){
+ Object modification =
+ ((CompositeModificationPayload) data).getModification();
+ commit(clientActor, modification);
+ } else {
+ LOG.error("Unknown state received {}", data);
+ }
+
+ }
+
+ @Override protected Object createSnapshot() {
+ throw new UnsupportedOperationException("createSnapshot");
+ }
+
+ @Override protected void applySnapshot(Object snapshot) {
+ throw new UnsupportedOperationException("applySnapshot");
+ }
+
+ @Override public String persistenceId() {
+ return this.name;
+ }
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
index 0363b3ceb3..5fbce4cd98 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java
@@ -19,6 +19,7 @@ import akka.japi.Creator;
import akka.japi.Function;
import com.google.common.base.Preconditions;
import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
@@ -56,7 +57,7 @@ public class ShardManager extends AbstractUntypedActor {
// Stores a mapping between a member name and the address of the member
private final Map memberNameToAddress = new HashMap<>();
- private final Map localShards = new HashMap<>();
+ private final Map localShards = new HashMap<>();
private final String type;
@@ -125,14 +126,20 @@ public class ShardManager extends AbstractUntypedActor {
}
private void memberUp(ClusterEvent.MemberUp message) {
- memberNameToAddress.put(message.member().roles().head(), message.member().address());
+ String memberName = message.member().roles().head();
+
+ memberNameToAddress.put(memberName , message.member().address());
+
+ for(ShardInformation info : localShards.values()){
+ String shardName = info.getShardName();
+ info.updatePeerAddress(getShardActorName(memberName, shardName),
+ getShardActorPath(shardName, memberName));
+ }
}
private void updateSchemaContext(Object message) {
- for(ActorPath path : localShards.values()){
- getContext().system().actorSelection(path)
- .forward(message,
- getContext());
+ for(ShardInformation info : localShards.values()){
+ info.getActor().tell(message,getSelf());
}
}
@@ -142,35 +149,50 @@ public class ShardManager extends AbstractUntypedActor {
List members =
configuration.getMembersFromShardName(shardName);
- for(String memberName : members) {
- if (memberName.equals(cluster.getCurrentMemberName())) {
- // This is a local shard
- ActorPath shardPath = localShards.get(shardName);
- if (shardPath == null) {
- getSender()
- .tell(new PrimaryNotFound(shardName).toSerializable(), getSelf());
- return;
- }
- getSender().tell(new PrimaryFound(shardPath.toString()).toSerializable(),
- getSelf());
+ // First see if the there is a local replica for the shard
+ ShardInformation info = localShards.get(shardName);
+ if(info != null) {
+ ActorPath shardPath = info.getActorPath();
+ if (shardPath != null) {
+ getSender()
+ .tell(
+ new PrimaryFound(shardPath.toString()).toSerializable(),
+ getSelf());
return;
- } else {
- Address address = memberNameToAddress.get(memberName);
- if(address != null){
- String path =
- address.toString() + "/user/shardmanager-" + this.type + "/" + getShardActorName(
- memberName, shardName);
- getSender().tell(new PrimaryFound(path).toSerializable(), getSelf());
- return;
- }
+ }
+ }
+ if(cluster.getCurrentMemberName() != null) {
+ members.remove(cluster.getCurrentMemberName());
+ }
+ // There is no way for us to figure out the primary (for now) so assume
+ // that one of the remote nodes is a primary
+ for(String memberName : members) {
+ Address address = memberNameToAddress.get(memberName);
+ if(address != null){
+ String path =
+ getShardActorPath(shardName, memberName);
+ getSender().tell(new PrimaryFound(path).toSerializable(), getSelf());
+ return;
}
}
-
getSender().tell(new PrimaryNotFound(shardName).toSerializable(), getSelf());
}
+ private String
+
+
+ getShardActorPath(String shardName, String memberName) {
+ Address address = memberNameToAddress.get(memberName);
+ if(address != null) {
+ return address.toString() + "/user/shardmanager-" + this.type + "/"
+ + getShardActorName(
+ memberName, shardName);
+ }
+ return null;
+ }
+
private String getShardActorName(String memberName, String shardName){
return memberName + "-shard-" + shardName + "-" + this.type;
}
@@ -183,14 +205,35 @@ public class ShardManager extends AbstractUntypedActor {
for(String shardName : memberShardNames){
String shardActorName = getShardActorName(memberName, shardName);
+ Map peerAddresses = getPeerAddresses(shardName);
ActorRef actor = getContext()
- .actorOf(Shard.props(shardActorName), shardActorName);
- ActorPath path = actor.path();
- localShards.put(shardName, path);
+ .actorOf(Shard.props(shardActorName, peerAddresses),
+ shardActorName);
+ localShards.put(shardName, new ShardInformation(shardName, actor, peerAddresses));
}
}
+ private Map getPeerAddresses(String shardName){
+
+ Map peerAddresses = new HashMap<>();
+
+ List members =
+ this.configuration.getMembersFromShardName(shardName);
+
+ String currentMemberName = this.cluster.getCurrentMemberName();
+
+ for(String memberName : members){
+ if(!currentMemberName.equals(memberName)){
+ String shardActorName = getShardActorName(memberName, shardName);
+ String path =
+ getShardActorPath(shardName, currentMemberName);
+ peerAddresses.put(shardActorName, path);
+ }
+ }
+ return peerAddresses;
+ }
+
@Override
public SupervisorStrategy supervisorStrategy() {
@@ -204,4 +247,49 @@ public class ShardManager extends AbstractUntypedActor {
);
}
+
+ private class ShardInformation {
+ private final String shardName;
+ private final ActorRef actor;
+ private final ActorPath actorPath;
+ private final Map peerAddresses;
+
+ private ShardInformation(String shardName, ActorRef actor,
+ Map peerAddresses) {
+ this.shardName = shardName;
+ this.actor = actor;
+ this.actorPath = actor.path();
+ this.peerAddresses = peerAddresses;
+ }
+
+ public String getShardName() {
+ return shardName;
+ }
+
+ public ActorRef getActor(){
+ return actor;
+ }
+
+ public ActorPath getActorPath() {
+ return actorPath;
+ }
+
+ public Map getPeerAddresses() {
+ return peerAddresses;
+ }
+
+ public void updatePeerAddress(String peerId, String peerAddress){
+ LOG.info("updatePeerAddress for peer {} with address {}", peerId, peerAddress);
+ if(peerAddresses.containsKey(peerId)){
+ peerAddresses.put(peerId, peerAddress);
+
+ LOG.info("Sending PeerAddressResolved for peer {} with address {} to {}", peerId, peerAddress, actor.path());
+
+ actor
+ .tell(new PeerAddressResolved(peerId, peerAddress),
+ getSelf());
+
+ }
+ }
+ }
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java
index 5a0049aa6d..c85d32012f 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java
@@ -9,10 +9,14 @@
package org.opendaylight.controller.cluster.datastore;
import akka.actor.ActorPath;
+import akka.actor.ActorRef;
import akka.actor.ActorSelection;
+import akka.actor.Props;
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
+import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException;
import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
@@ -30,6 +34,8 @@ import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCoh
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
@@ -60,6 +66,10 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
private static final AtomicLong counter = new AtomicLong();
+ private static final Logger
+ LOG = LoggerFactory.getLogger(TransactionProxy.class);
+
+
private final TransactionType transactionType;
private final ActorContext actorContext;
private final Map remoteTransactionPaths = new HashMap<>();
@@ -72,7 +82,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
TransactionType transactionType,
ExecutorService executor,
SchemaContext schemaContext
- ) {
+ ) {
this.identifier = actorContext.getCurrentMemberName() + "-txn-" + counter.getAndIncrement();
this.transactionType = transactionType;
@@ -88,33 +98,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
createTransactionIfMissing(actorContext, path);
- final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
-
- Callable>> call = new Callable() {
-
- @Override public Optional> call() throws Exception {
- Object response = actorContext
- .executeRemoteOperation(remoteTransaction, new ReadData(path).toSerializable(),
- ActorContext.ASK_DURATION);
- if(response.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)){
- ReadDataReply reply = ReadDataReply.fromSerializable(schemaContext,path, response);
- if(reply.getNormalizedNode() == null){
- return Optional.absent();
- }
- //FIXME : A cast should not be required here ???
- return (Optional>) Optional.of(reply.getNormalizedNode());
- }
-
- return Optional.absent();
- }
- };
-
- ListenableFutureTask>>
- future = ListenableFutureTask.create(call);
-
- executor.submit(future);
-
- return future;
+ return transactionContext(path).readData(path);
}
@Override
@@ -122,8 +106,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
createTransactionIfMissing(actorContext, path);
- final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
- remoteTransaction.tell(new WriteData(path, data, schemaContext).toSerializable(), null);
+ transactionContext(path).writeData(path, data);
}
@Override
@@ -131,8 +114,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
createTransactionIfMissing(actorContext, path);
- final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
- remoteTransaction.tell(new MergeData(path, data, schemaContext).toSerializable(), null);
+ transactionContext(path).mergeData(path, data);
}
@Override
@@ -140,8 +122,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
createTransactionIfMissing(actorContext, path);
- final ActorSelection remoteTransaction = remoteTransactionFromIdentifier(path);
- remoteTransaction.tell(new DeleteData(path).toSerializable(), null);
+ transactionContext(path).deleteData(path);
}
@Override
@@ -149,10 +130,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
List cohortPaths = new ArrayList<>();
for(TransactionContext transactionContext : remoteTransactionPaths.values()) {
- Object result = actorContext.executeRemoteOperation(transactionContext.getActor(),
- new ReadyTransaction().toSerializable(),
- ActorContext.ASK_DURATION
- );
+ Object result = transactionContext.readyTransaction();
if(result.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)){
ReadyTransactionReply reply = ReadyTransactionReply.fromSerializable(actorContext.getActorSystem(),result);
@@ -173,14 +151,13 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
@Override
public void close() {
for(TransactionContext transactionContext : remoteTransactionPaths.values()) {
- transactionContext.getActor().tell(
- new CloseTransaction().toSerializable(), null);
+ transactionContext.closeTransaction();
}
}
- private ActorSelection remoteTransactionFromIdentifier(YangInstanceIdentifier path){
+ private TransactionContext transactionContext(YangInstanceIdentifier path){
String shardName = shardNameFromIdentifier(path);
- return remoteTransactionPaths.get(shardName).getActor();
+ return remoteTransactionPaths.get(shardName);
}
private String shardNameFromIdentifier(YangInstanceIdentifier path){
@@ -198,48 +175,186 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
return;
}
- Object response = actorContext.executeShardOperation(shardName, new CreateTransaction(identifier).toSerializable(), ActorContext.ASK_DURATION);
- if(response.getClass().equals(CreateTransactionReply.SERIALIZABLE_CLASS)){
- CreateTransactionReply reply = CreateTransactionReply.fromSerializable(response);
- String transactionPath = actorContext.getRemoteActorPath(shardName, reply.getTransactionPath());
+ try {
+ Object response = actorContext.executeShardOperation(shardName,
+ new CreateTransaction(identifier).toSerializable(),
+ ActorContext.ASK_DURATION);
+ if (response.getClass()
+ .equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
+ CreateTransactionReply reply =
+ CreateTransactionReply.fromSerializable(response);
+
+ String transactionPath = reply.getTransactionPath();
- ActorSelection transactionActor = actorContext.actorSelection(transactionPath);
- transactionContext = new TransactionContext(shardName, transactionPath, transactionActor);
+ LOG.info("Received transaction path = {}" , transactionPath );
- remoteTransactionPaths.put(shardName, transactionContext);
+ ActorSelection transactionActor =
+ actorContext.actorSelection(transactionPath);
+ transactionContext =
+ new TransactionContextImpl(shardName, transactionPath,
+ transactionActor);
+
+ remoteTransactionPaths.put(shardName, transactionContext);
+ }
+ } catch(TimeoutException e){
+ remoteTransactionPaths.put(shardName, new NoOpTransactionContext(shardName));
}
}
+ private interface TransactionContext {
+ String getShardName();
+
+ String getResolvedCohortPath(String cohortPath);
+
+ public void closeTransaction();
+
+ public Object readyTransaction();
- private class TransactionContext {
+ void deleteData(YangInstanceIdentifier path);
+
+ void mergeData(YangInstanceIdentifier path, NormalizedNode, ?> data);
+
+ ListenableFuture>> readData(final YangInstanceIdentifier path);
+
+ void writeData(YangInstanceIdentifier path, NormalizedNode, ?> data);
+ }
+
+
+ private class TransactionContextImpl implements TransactionContext{
private final String shardName;
private final String actorPath;
private final ActorSelection actor;
- private TransactionContext(String shardName, String actorPath,
+ private TransactionContextImpl(String shardName, String actorPath,
ActorSelection actor) {
this.shardName = shardName;
this.actorPath = actorPath;
this.actor = actor;
}
-
- public String getShardName() {
+ @Override public String getShardName() {
return shardName;
}
- public String getActorPath() {
- return actorPath;
- }
-
- public ActorSelection getActor() {
+ private ActorSelection getActor() {
return actor;
}
- public String getResolvedCohortPath(String cohortPath){
+ @Override public String getResolvedCohortPath(String cohortPath){
return actorContext.resolvePath(actorPath, cohortPath);
}
+
+ @Override public void closeTransaction() {
+ getActor().tell(
+ new CloseTransaction().toSerializable(), null);
+ }
+
+ @Override public Object readyTransaction() {
+ return actorContext.executeRemoteOperation(getActor(),
+ new ReadyTransaction().toSerializable(),
+ ActorContext.ASK_DURATION
+ );
+
+ }
+
+ @Override public void deleteData(YangInstanceIdentifier path) {
+ getActor().tell(new DeleteData(path).toSerializable(), null);
+ }
+
+ @Override public void mergeData(YangInstanceIdentifier path, NormalizedNode, ?> data){
+ getActor().tell(new MergeData(path, data, schemaContext).toSerializable(), null);
+ }
+
+ @Override public ListenableFuture>> readData(final YangInstanceIdentifier path) {
+
+ Callable>> call = new Callable() {
+
+ @Override public Optional> call() throws Exception {
+ Object response = actorContext
+ .executeRemoteOperation(getActor(), new ReadData(path).toSerializable(),
+ ActorContext.ASK_DURATION);
+ if(response.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)){
+ ReadDataReply reply = ReadDataReply.fromSerializable(schemaContext,path, response);
+ if(reply.getNormalizedNode() == null){
+ return Optional.absent();
+ }
+ //FIXME : A cast should not be required here ???
+ return (Optional>) Optional.of(reply.getNormalizedNode());
+ }
+
+ return Optional.absent();
+ }
+ };
+
+ ListenableFutureTask>>
+ future = ListenableFutureTask.create(call);
+
+ executor.submit(future);
+
+ return future;
+ }
+
+ @Override public void writeData(YangInstanceIdentifier path, NormalizedNode, ?> data) {
+ getActor().tell(new WriteData(path, data, schemaContext).toSerializable(), null);
+ }
+
+ }
+
+ private class NoOpTransactionContext implements TransactionContext {
+
+ private final Logger
+ LOG = LoggerFactory.getLogger(NoOpTransactionContext.class);
+
+ private final String shardName;
+
+ private ActorRef cohort;
+
+ public NoOpTransactionContext(String shardName){
+ this.shardName = shardName;
+ }
+ @Override public String getShardName() {
+ return shardName;
+
+ }
+
+ @Override public String getResolvedCohortPath(String cohortPath) {
+ return cohort.path().toString();
+ }
+
+ @Override public void closeTransaction() {
+ LOG.error("closeTransaction called");
+ }
+
+ @Override public Object readyTransaction() {
+ LOG.error("readyTransaction called");
+ cohort = actorContext.getActorSystem().actorOf(Props.create(NoOpCohort.class));
+ return new ReadyTransactionReply(cohort.path()).toSerializable();
+ }
+
+ @Override public void deleteData(YangInstanceIdentifier path) {
+ LOG.error("deleteData called path = {}", path);
+ }
+
+ @Override public void mergeData(YangInstanceIdentifier path,
+ NormalizedNode, ?> data) {
+ LOG.error("mergeData called path = {}", path);
+ }
+
+ @Override
+ public ListenableFuture>> readData(
+ YangInstanceIdentifier path) {
+ LOG.error("readData called path = {}", path);
+ return Futures.immediateFuture(
+ Optional.>absent());
+ }
+
+ @Override public void writeData(YangInstanceIdentifier path,
+ NormalizedNode, ?> data) {
+ LOG.error("writeData called path = {}", path);
+ }
}
+
+
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/PrimaryNotFoundException.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/PrimaryNotFoundException.java
index 5a131ade33..7b07053fd9 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/PrimaryNotFoundException.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/PrimaryNotFoundException.java
@@ -9,4 +9,7 @@
package org.opendaylight.controller.cluster.datastore.exceptions;
public class PrimaryNotFoundException extends RuntimeException {
+ public PrimaryNotFoundException(String message){
+ super(message);
+ }
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/TimeoutException.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/TimeoutException.java
index 4780aaccfb..472cd38734 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/TimeoutException.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/exceptions/TimeoutException.java
@@ -9,7 +9,7 @@
package org.opendaylight.controller.cluster.datastore.exceptions;
public class TimeoutException extends RuntimeException {
- public TimeoutException(Exception e){
- super(e);
+ public TimeoutException(String message, Exception e){
+ super(message, e);
}
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PeerAddressResolved.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PeerAddressResolved.java
new file mode 100644
index 0000000000..8c2543e486
--- /dev/null
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/PeerAddressResolved.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 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.controller.cluster.datastore.messages;
+
+public class PeerAddressResolved {
+ private final String peerId;
+ private final String peerAddress;
+
+ public PeerAddressResolved(String peerId, String peerAddress) {
+ this.peerId = peerId;
+ this.peerAddress = peerAddress;
+ }
+
+ public String getPeerId() {
+ return peerId;
+ }
+
+ public String getPeerAddress() {
+ return peerAddress;
+ }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
index c7ee7d8c2c..ac0893da5a 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/utils/ActorContext.java
@@ -14,9 +14,6 @@ import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
import akka.actor.PoisonPill;
import akka.util.Timeout;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
import org.opendaylight.controller.cluster.datastore.ClusterWrapper;
import org.opendaylight.controller.cluster.datastore.Configuration;
import org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException;
@@ -105,7 +102,7 @@ public class ActorContext {
return found.getPrimaryPath();
}
- throw new PrimaryNotFoundException();
+ throw new PrimaryNotFoundException("Could not find primary for shardName " + shardName);
}
@@ -125,7 +122,7 @@ public class ActorContext {
try {
return Await.result(future, AWAIT_DURATION);
} catch (Exception e) {
- throw new TimeoutException(e);
+ throw new TimeoutException("Sending message " + message.getClass().toString() + " to actor " + actor.toString() + " failed" , e);
}
}
@@ -148,7 +145,7 @@ public class ActorContext {
try {
return Await.result(future, AWAIT_DURATION);
} catch (Exception e) {
- throw new TimeoutException(e);
+ throw new TimeoutException("Sending message " + message.getClass().toString() + " to actor " + actor.toString() + " failed" , e);
}
}
@@ -178,22 +175,15 @@ public class ActorContext {
actorSystem.shutdown();
}
- public String getRemoteActorPath(final String shardName,
- final String localPathOfRemoteActor) {
- final String path = findPrimaryPath(shardName);
-
- LoadingCache graphs = CacheBuilder.newBuilder()
- .expireAfterAccess(2, TimeUnit.SECONDS)
- .build(
- new CacheLoader() {
- public String load(String key) {
- return resolvePath(path, localPathOfRemoteActor);
- }
- }
- );
- return graphs.getUnchecked(localPathOfRemoteActor);
- }
-
+ /**
+ * @deprecated Need to stop using this method. There are ways to send a
+ * remote ActorRef as a string which should be used instead of this hack
+ *
+ * @param primaryPath
+ * @param localPathOfRemoteActor
+ * @return
+ */
+ @Deprecated
public String resolvePath(final String primaryPath,
final String localPathOfRemoteActor) {
StringBuilder builder = new StringBuilder();
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java
index 214b3e9d3d..e23a76b0b2 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java
@@ -10,22 +10,38 @@ package org.opendaylight.controller.cluster.datastore;
import akka.actor.ActorSystem;
import akka.testkit.JavaTestKit;
+import org.apache.commons.io.FileUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
+import java.io.File;
+import java.io.IOException;
+
public abstract class AbstractActorTest {
private static ActorSystem system;
@BeforeClass
- public static void setUpClass() {
+ public static void setUpClass() throws IOException {
+ File journal = new File("journal");
+
+ if(journal.exists()) {
+ FileUtils.deleteDirectory(journal);
+ }
+
System.setProperty("shard.persistent", "false");
system = ActorSystem.create("test");
}
@AfterClass
- public static void tearDownClass() {
+ public static void tearDownClass() throws IOException {
JavaTestKit.shutdownActorSystem(system);
system = null;
+
+ File journal = new File("journal");
+
+ if(journal.exists()) {
+ FileUtils.deleteDirectory(journal);
+ }
}
protected ActorSystem getSystem() {
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java
index b62a4b36d5..11ad559744 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/BasicIntegrationTest.java
@@ -33,6 +33,8 @@ import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.FiniteDuration;
+import java.util.Collections;
+
public class BasicIntegrationTest extends AbstractActorTest {
@Test
@@ -47,16 +49,25 @@ public class BasicIntegrationTest extends AbstractActorTest {
new JavaTestKit(getSystem()) {{
- final Props props = Shard.props("config");
+ final Props props = Shard.props("config", Collections.EMPTY_MAP);
final ActorRef shard = getSystem().actorOf(props);
new Within(duration("5 seconds")) {
protected void run() {
+
shard.tell(
new UpdateSchemaContext(TestModel.createTestContext()),
getRef());
+
+ // Wait for Shard to become a Leader
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // 1. Create a TransactionChain
shard.tell(new CreateTransactionChain().toSerializable(), getRef());
final ActorSelection transactionChain =
@@ -76,6 +87,9 @@ public class BasicIntegrationTest extends AbstractActorTest {
Assert.assertNotNull(transactionChain);
+ System.out.println("Successfully created transaction chain");
+
+ // 2. Create a Transaction on the TransactionChain
transactionChain.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
final ActorSelection transaction =
@@ -94,9 +108,9 @@ public class BasicIntegrationTest extends AbstractActorTest {
Assert.assertNotNull(transaction);
- // Add a watch on the transaction actor so that we are notified when it dies
- final ActorRef transactionActorRef = watchActor(transaction);
+ System.out.println("Successfully created transaction");
+ // 3. Write some data
transaction.tell(new WriteData(TestModel.TEST_PATH,
ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
getRef());
@@ -113,6 +127,10 @@ public class BasicIntegrationTest extends AbstractActorTest {
Assert.assertTrue(writeDone);
+ System.out.println("Successfully wrote data");
+
+ // 4. Ready the transaction for commit
+
transaction.tell(new ReadyTransaction().toSerializable(), getRef());
final ActorSelection cohort =
@@ -132,8 +150,9 @@ public class BasicIntegrationTest extends AbstractActorTest {
Assert.assertNotNull(cohort);
- // Add a watch on the transaction actor so that we are notified when it dies
- final ActorRef cohorActorRef = watchActor(cohort);
+ System.out.println("Successfully readied the transaction");
+
+ // 5. PreCommit the transaction
cohort.tell(new PreCommitTransaction().toSerializable(), getRef());
@@ -150,10 +169,14 @@ public class BasicIntegrationTest extends AbstractActorTest {
Assert.assertTrue(preCommitDone);
+ System.out.println("Successfully pre-committed the transaction");
+
+ // 6. Commit the transaction
cohort.tell(new CommitTransaction().toSerializable(), getRef());
// FIXME : Add assertions that the commit worked and that the cohort and transaction actors were terminated
+ System.out.println("TODO : Check Successfully committed the transaction");
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java
index 116e5e75b5..b5e3d24ef6 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreIntegrationTest.java
@@ -9,7 +9,6 @@ import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
-import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration;
import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel;
import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
@@ -46,12 +45,15 @@ public class DistributedDataStoreIntegrationTest{
@Test
public void integrationTest() throws Exception {
- ShardStrategyFactory.setConfiguration(new MockConfiguration());
+ Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+ ShardStrategyFactory.setConfiguration(configuration);
DistributedDataStore distributedDataStore =
- new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), new MockConfiguration());
+ new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
+ Thread.sleep(1000);
+
DOMStoreReadWriteTransaction transaction =
distributedDataStore.newReadWriteTransaction();
@@ -95,6 +97,8 @@ public class DistributedDataStoreIntegrationTest{
distributedDataStore.onGlobalContextUpdated(SchemaContextHelper.full());
+ Thread.sleep(1000);
+
DOMStoreReadWriteTransaction transaction =
distributedDataStore.newReadWriteTransaction();
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
index f20cd8c3d7..7d57ea8284 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
@@ -7,6 +7,7 @@ import org.junit.Test;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.PeerAddressResolved;
import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
@@ -19,6 +20,10 @@ import org.opendaylight.controller.protobuff.messages.transaction.ShardTransacti
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -26,10 +31,18 @@ public class ShardTest extends AbstractActorTest {
@Test
public void testOnReceiveCreateTransactionChain() throws Exception {
new JavaTestKit(getSystem()) {{
- final Props props = Shard.props("config");
+ final Props props = Shard.props("config", Collections.EMPTY_MAP);
final ActorRef subject =
getSystem().actorOf(props, "testCreateTransactionChain");
+
+ // Wait for Shard to become a Leader
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
new Within(duration("1 seconds")) {
protected void run() {
@@ -64,7 +77,7 @@ public class ShardTest extends AbstractActorTest {
@Test
public void testOnReceiveRegisterListener() throws Exception {
new JavaTestKit(getSystem()) {{
- final Props props = Shard.props("config");
+ final Props props = Shard.props("config", Collections.EMPTY_MAP);
final ActorRef subject =
getSystem().actorOf(props, "testRegisterChangeListener");
@@ -107,10 +120,19 @@ public class ShardTest extends AbstractActorTest {
@Test
public void testCreateTransaction(){
new JavaTestKit(getSystem()) {{
- final Props props = Shard.props("config");
+ final Props props = Shard.props("config", Collections.EMPTY_MAP);
final ActorRef subject =
getSystem().actorOf(props, "testCreateTransaction");
+
+ // Wait for Shard to become a Leader
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+
new Within(duration("1 seconds")) {
protected void run() {
@@ -135,9 +157,8 @@ public class ShardTest extends AbstractActorTest {
}
}.get(); // this extracts the received message
- assertEquals("Unexpected transaction path " + out,
- "akka://test/user/testCreateTransaction/shard-txn-1",
- out);
+ assertTrue("Unexpected transaction path " + out,
+ out.contains("akka://test/user/testCreateTransaction/shard-txn-1"));
expectNoMsg();
}
@@ -146,7 +167,29 @@ public class ShardTest extends AbstractActorTest {
}};
}
+ @Test
+ public void testPeerAddressResolved(){
+ new JavaTestKit(getSystem()) {{
+ Map peerAddresses = new HashMap<>();
+ peerAddresses.put("member-2", null);
+ final Props props = Shard.props("config", peerAddresses);
+ final ActorRef subject =
+ getSystem().actorOf(props, "testPeerAddressResolved");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+ subject.tell(
+ new PeerAddressResolved("member-2", "akka://foobar"),
+ getRef());
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
private AsyncDataChangeListener> noOpDataChangeListener() {
return new AsyncDataChangeListener>() {
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
index 4d7c61a197..7884eeccda 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
@@ -30,6 +30,8 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import java.util.Collections;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -49,7 +51,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveReadData() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
final ActorRef subject = getSystem().actorOf(props, "testReadData");
@@ -89,7 +91,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveReadDataWhenDataNotFound() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
@@ -163,7 +165,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveWriteData() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
@@ -201,7 +203,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveMergeData() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
final ActorRef subject =
@@ -240,7 +242,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveDeleteData() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
@@ -277,7 +279,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveReadyTransaction() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
@@ -313,7 +315,7 @@ public class ShardTransactionTest extends AbstractActorTest {
@Test
public void testOnReceiveCloseTransaction() throws Exception {
new JavaTestKit(getSystem()) {{
- final ActorRef shard = getSystem().actorOf(Shard.props("config"));
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/CarsModel.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/CarsModel.java
index 57df20172d..6860872b75 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/CarsModel.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/CarsModel.java
@@ -8,6 +8,7 @@
package org.opendaylight.controller.md.cluster.datastore.model;
+import java.math.BigInteger;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -42,14 +43,14 @@ public class CarsModel {
MapEntryNode altima =
ImmutableNodes.mapEntryBuilder(CAR_QNAME, CAR_NAME_QNAME, "altima")
.withChild(ImmutableNodes.leafNode(CAR_NAME_QNAME, "altima"))
- .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, 1000))
+ .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, new BigInteger("1000")))
.build();
// Create an entry for the car accord
MapEntryNode honda =
ImmutableNodes.mapEntryBuilder(CAR_QNAME, CAR_NAME_QNAME, "accord")
.withChild(ImmutableNodes.leafNode(CAR_NAME_QNAME, "accord"))
- .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, 2000))
+ .withChild(ImmutableNodes.leafNode(CAR_PRICE_QNAME, new BigInteger("2000")))
.build();
cars.withChild(altima);
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java
index 1b4020af43..e637920e78 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/PeopleModel.java
@@ -42,14 +42,14 @@ public class PeopleModel {
MapEntryNode jack =
ImmutableNodes.mapEntryBuilder(PERSON_QNAME, PERSON_NAME_QNAME, "jack")
.withChild(ImmutableNodes.leafNode(PERSON_NAME_QNAME, "jack"))
- .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 100))
+ .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 100L))
.build();
// Create an entry for the person jill
MapEntryNode jill =
ImmutableNodes.mapEntryBuilder(PERSON_QNAME, PERSON_NAME_QNAME, "jill")
.withChild(ImmutableNodes.leafNode(PERSON_NAME_QNAME, "jill"))
- .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 200))
+ .withChild(ImmutableNodes.leafNode(PERSON_AGE_QNAME, 200L))
.build();
cars.withChild(jack);
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/SampleModelsTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/SampleModelsTest.java
index d8fefcd986..be8713c702 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/SampleModelsTest.java
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/SampleModelsTest.java
@@ -18,45 +18,45 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
public class SampleModelsTest {
@Test
public void testPeopleModel(){
- NormalizedNode, ?> expected = PeopleModel.create();
+ final NormalizedNode, ?> expected = PeopleModel.create();
- NormalizedNodeMessages.Container node =
+ final NormalizedNodeMessages.Container node =
new NormalizedNodeToNodeCodec(SchemaContextHelper.full())
.encode(YangInstanceIdentifier.of(PeopleModel.BASE_QNAME),
expected);
- NormalizedNodeMessages.Node normalizedNode =
+ final NormalizedNodeMessages.Node normalizedNode =
node.getNormalizedNode();
- NormalizedNode,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(YangInstanceIdentifier.of(PeopleModel.BASE_QNAME),
+ final NormalizedNode,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(YangInstanceIdentifier.of(PeopleModel.BASE_QNAME),
normalizedNode);
- Assert.assertEquals(expected.toString(), actual.toString());
+ Assert.assertEquals(expected, actual);
}
@Test
public void testCarsModel(){
- NormalizedNode, ?> expected = CarsModel.create();
+ final NormalizedNode, ?> expected = CarsModel.create();
- NormalizedNodeMessages.Container node =
+ final NormalizedNodeMessages.Container node =
new NormalizedNodeToNodeCodec(SchemaContextHelper.full())
.encode(YangInstanceIdentifier.of(CarsModel.BASE_QNAME),
expected);
- NormalizedNodeMessages.Node normalizedNode =
+ final NormalizedNodeMessages.Node normalizedNode =
node.getNormalizedNode();
- NormalizedNode,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(
+ final NormalizedNode,?> actual = new NormalizedNodeToNodeCodec(SchemaContextHelper.full()).decode(
YangInstanceIdentifier.of(CarsModel.BASE_QNAME),
normalizedNode);
- Assert.assertEquals(expected.toString(), actual.toString());
+ Assert.assertEquals(expected, actual);
}
}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/module-shards.conf b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/module-shards.conf
index 9f35f2b9f2..b3de998479 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/module-shards.conf
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/module-shards.conf
@@ -18,9 +18,7 @@ module-shards = [
{
name="people-1"
replicas = [
- "member-1",
- "member-2",
- "member-3"
+ "member-1"
]
}
]
@@ -31,9 +29,18 @@ module-shards = [
{
name="cars-1"
replicas = [
- "member-4",
- "member-1",
- "member-5"
+ "member-1"
+ ]
+ }
+ ]
+ },
+ {
+ name = "test"
+ shards = [
+ {
+ name="test-1"
+ replicas = [
+ "member-1"
]
}
]
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/modules.conf b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/modules.conf
index 52f249a7ff..22854cb11a 100644
--- a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/modules.conf
+++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/modules.conf
@@ -8,6 +8,11 @@ modules = [
name = "cars"
namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:cars"
shard-strategy = "module"
+ },
+ {
+ name = "test"
+ namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test"
+ shard-strategy = "module"
}
]
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
index 34e5b1b803..c3e979c536 100644
--- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
+++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/model/SchemaService.java
@@ -11,7 +11,7 @@ import org.opendaylight.controller.sal.core.api.BrokerService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
public interface SchemaService extends BrokerService {
@@ -42,5 +42,11 @@ public interface SchemaService extends BrokerService {
*/
SchemaContext getGlobalContext();
- ListenerRegistration registerSchemaServiceListener(SchemaServiceListener listener);
+ /**
+ * Register a listener for changes in schema context.
+ *
+ * @param listener Listener which should be registered
+ * @return Listener registration handle
+ */
+ ListenerRegistration registerSchemaContextListener(SchemaContextListener listener);
}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java
index 17b78f4ebd..f1f16cd635 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java
@@ -91,7 +91,7 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi
wrappedStore.changeDelegate(legacyStore);
wrappedStore.setValidationEnabled(false);
- schemaService.registerSchemaServiceListener(wrappedStore);
+ schemaService.registerSchemaContextListener(wrappedStore);
dataService.registerConfigurationReader(rootPath, wrappedStore);
dataService.registerCommitHandler(rootPath, wrappedStore);
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java
index 69b17ee3c4..667c0fc282 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomInmemoryDataBrokerModule.java
@@ -50,7 +50,7 @@ public final class DomInmemoryDataBrokerModule extends
//we will default to InMemoryDOMDataStore creation
operStore = new InMemoryDOMDataStore("DOM-OPER", storeExecutor);
//here we will register the SchemaContext listener
- getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)operStore);
+ getSchemaServiceDependency().registerSchemaContextListener((InMemoryDOMDataStore)operStore);
}
DOMStore configStore = getConfigDataStoreDependency();
@@ -58,7 +58,7 @@ public final class DomInmemoryDataBrokerModule extends
//we will default to InMemoryDOMDataStore creation
configStore = new InMemoryDOMDataStore("DOM-CFG", storeExecutor);
//here we will register the SchemaContext listener
- getSchemaServiceDependency().registerSchemaServiceListener((InMemoryDOMDataStore)configStore);
+ getSchemaServiceDependency().registerSchemaContextListener((InMemoryDOMDataStore)configStore);
}
ImmutableMap datastores = ImmutableMap
. builder().put(LogicalDatastoreType.OPERATIONAL, operStore)
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java
index fbc418dc2a..62b026430a 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java
@@ -13,7 +13,7 @@ import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -90,8 +90,8 @@ org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImp
}
@Override
- public ListenerRegistration registerSchemaServiceListener(final SchemaServiceListener arg0) {
- return delegate.registerSchemaServiceListener(arg0);
+ public ListenerRegistration registerSchemaContextListener(final SchemaContextListener arg0) {
+ return delegate.registerSchemaContextListener(arg0);
}
@Override
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleDataBroker.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleDataBroker.java
index e8f8da53c9..dc122cfdc2 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleDataBroker.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleDataBroker.java
@@ -1,3 +1,10 @@
+/*
+ * Copyright (c) 2014 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.controller.md.sal.dom.broker.impl.compat;
import javax.annotation.concurrent.ThreadSafe;
@@ -21,18 +28,17 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
@ThreadSafe
public class BackwardsCompatibleDataBroker implements DataProviderService {
private final DOMDataBroker backingBroker;
private volatile DataNormalizer normalizer;
- private final ListenerRegistration schemaReg;
+ private final ListenerRegistration schemaReg;
public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl, final SchemaService schemaService) {
backingBroker = newBiDataImpl;
- schemaReg = schemaService.registerSchemaServiceListener(new SchemaListener());
+ schemaReg = schemaService.registerSchemaContextListener(new SchemaListener());
}
@Override
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java
index d837d75ddc..61ea47e39b 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java
@@ -72,7 +72,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
public class BackwardsCompatibleMountPoint implements MountProvisionInstance, SchemaContextProvider, SchemaService {
@@ -83,7 +83,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
private final NotificationPublishService notificationPublishService;
private final RpcProvisionRegistry rpcs;
- private final ListenerRegistry schemaListenerRegistry = new ListenerRegistry<>();
+ private final ListenerRegistry schemaListenerRegistry = new ListenerRegistry<>();
private SchemaContext schemaContext;
@@ -154,7 +154,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
}
@Override
- public ListenerRegistration registerSchemaServiceListener(final SchemaServiceListener listener) {
+ public ListenerRegistration registerSchemaContextListener(final SchemaContextListener listener) {
return schemaListenerRegistry.register(listener);
}
@@ -275,7 +275,7 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
@Override
public void setSchemaContext(final SchemaContext schemaContext) {
this.schemaContext = schemaContext;
- for (ListenerRegistration schemaServiceListenerListenerRegistration : schemaListenerRegistry.getListeners()) {
+ for (ListenerRegistration schemaServiceListenerListenerRegistration : schemaListenerRegistry.getListeners()) {
schemaServiceListenerListenerRegistration.getInstance().onGlobalContextUpdated(schemaContext);
}
}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java
index d8174c312a..82637327f6 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java
@@ -23,7 +23,7 @@ import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.opendaylight.yangtools.yang.parser.impl.util.URLSchemaContextResolver;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -40,15 +40,15 @@ import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
-public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer, AutoCloseable {
+public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class);
- private final ListenerRegistry listeners = new ListenerRegistry<>();
+ private final ListenerRegistry listeners = new ListenerRegistry<>();
private final URLSchemaContextResolver contextResolver = new URLSchemaContextResolver();
private final BundleScanner scanner = new BundleScanner();
private final BundleContext context;
- private ServiceTracker listenerTracker;
+ private ServiceTracker listenerTracker;
private BundleTracker> bundleTracker;
private boolean starting = true;
private static GlobalBundleScanningSchemaServiceImpl instance;
@@ -81,7 +81,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
public void start() {
checkState(context != null);
- listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, GlobalBundleScanningSchemaServiceImpl.this);
+ listenerTracker = new ServiceTracker<>(context, SchemaContextListener.class, GlobalBundleScanningSchemaServiceImpl.this);
bundleTracker = new BundleTracker<>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
bundleTracker.open();
listenerTracker.open();
@@ -115,7 +115,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
}
@Override
- public synchronized ListenerRegistration registerSchemaServiceListener(final SchemaServiceListener listener) {
+ public synchronized ListenerRegistration registerSchemaContextListener(final SchemaContextListener listener) {
Optional potentialCtx = contextResolver.getSchemaContext();
if(potentialCtx.isPresent()) {
listener.onGlobalContextUpdated(potentialCtx.get());
@@ -137,7 +137,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
private synchronized void updateContext(final SchemaContext snapshot) {
Object[] services = listenerTracker.getServices();
- for (ListenerRegistration listener : listeners) {
+ for (ListenerRegistration listener : listeners) {
try {
listener.getInstance().onGlobalContextUpdated(snapshot);
} catch (Exception e) {
@@ -146,7 +146,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
}
if (services != null) {
for (Object rawListener : services) {
- SchemaServiceListener listener = (SchemaServiceListener) rawListener;
+ final SchemaContextListener listener = (SchemaContextListener) rawListener;
try {
listener.onGlobalContextUpdated(snapshot);
} catch (Exception e) {
@@ -213,9 +213,9 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
}
@Override
- public synchronized SchemaServiceListener addingService(final ServiceReference reference) {
+ public synchronized SchemaContextListener addingService(final ServiceReference reference) {
- SchemaServiceListener listener = context.getService(reference);
+ SchemaContextListener listener = context.getService(reference);
SchemaContext _ctxContext = getGlobalContext();
if (getContext() != null && _ctxContext != null) {
listener.onGlobalContextUpdated(_ctxContext);
@@ -234,12 +234,12 @@ public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvi
}
@Override
- public void modifiedService(final ServiceReference reference, final SchemaServiceListener service) {
+ public void modifiedService(final ServiceReference reference, final SchemaContextListener service) {
// NOOP
}
@Override
- public void removedService(final ServiceReference reference, final SchemaServiceListener service) {
+ public void removedService(final ServiceReference reference, final SchemaContextListener service) {
context.ungetService(reference);
}
}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java
index 1d864eec5b..d8d2346a8c 100644
--- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java
+++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceProxy.java
@@ -8,10 +8,10 @@
package org.opendaylight.controller.sal.dom.broker.osgi;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.osgi.framework.ServiceReference;
public class SchemaServiceProxy extends AbstractBrokerServiceProxy implements SchemaService {
@@ -41,12 +41,9 @@ public class SchemaServiceProxy extends AbstractBrokerServiceProxy registerSchemaServiceListener(SchemaServiceListener listener) {
- ListenerRegistration registration = getDelegate().registerSchemaServiceListener(listener);
+ public ListenerRegistration registerSchemaContextListener(SchemaContextListener listener) {
+ ListenerRegistration registration = getDelegate().registerSchemaContextListener(listener);
addRegistration(registration);
return registration;
}
-
-
-
}
diff --git a/opendaylight/md-sal/sal-dom-xsql/src/main/java/org/opendaylight/yang/gen/v1/http/netconfcentral/org/ns/xsql/rev140626/XSQLModule.java b/opendaylight/md-sal/sal-dom-xsql/src/main/java/org/opendaylight/yang/gen/v1/http/netconfcentral/org/ns/xsql/rev140626/XSQLModule.java
index 399f49bd6b..59cdc76e7a 100644
--- a/opendaylight/md-sal/sal-dom-xsql/src/main/java/org/opendaylight/yang/gen/v1/http/netconfcentral/org/ns/xsql/rev140626/XSQLModule.java
+++ b/opendaylight/md-sal/sal-dom-xsql/src/main/java/org/opendaylight/yang/gen/v1/http/netconfcentral/org/ns/xsql/rev140626/XSQLModule.java
@@ -20,7 +20,7 @@ public class XSQLModule extends org.opendaylight.yang.gen.v1.http.netconfcentral
@Override
public java.lang.AutoCloseable createInstance() {
XSQLAdapter xsqlAdapter = XSQLAdapter.getInstance();
- getSchemaServiceDependency().registerSchemaServiceListener(xsqlAdapter);
+ getSchemaServiceDependency().registerSchemaContextListener(xsqlAdapter);
xsqlAdapter.setDataBroker(getAsyncDataBrokerDependency());
XSQLProvider p = new XSQLProvider();
p.buildXSQL(getDataBrokerDependency());
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
index 01a5989dcd..805608d479 100644
--- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
+++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryConfigDataStoreProviderModule.java
@@ -23,7 +23,7 @@ public class InMemoryConfigDataStoreProviderModule extends org.opendaylight.cont
@Override
public java.lang.AutoCloseable createInstance() {
InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-CFG", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
- getSchemaServiceDependency().registerSchemaServiceListener(ids);
+ getSchemaServiceDependency().registerSchemaContextListener(ids);
return ids;
}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
index b39c9bbbd8..f4795588ab 100644
--- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
+++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/config/yang/inmemory_datastore_provider/InMemoryOperationalDataStoreProviderModule.java
@@ -23,7 +23,7 @@ public class InMemoryOperationalDataStoreProviderModule extends org.opendaylight
@Override
public java.lang.AutoCloseable createInstance() {
InMemoryDOMDataStore ids = new InMemoryDOMDataStore("DOM-OPER", MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
- getOperationalSchemaServiceDependency().registerSchemaServiceListener(ids);
+ getOperationalSchemaServiceDependency().registerSchemaContextListener(ids);
return ids;
}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
index 037bfb4a82..b75df80f4e 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/md/sal/connector/netconf/NetconfConnectorModule.java
@@ -13,8 +13,10 @@ import static org.opendaylight.controller.config.api.JmxAttributeValidationExcep
import java.io.File;
import java.io.InputStream;
import java.net.InetSocketAddress;
+import java.util.List;
import java.util.concurrent.ExecutorService;
+import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
@@ -24,6 +26,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
+import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceSalFacade;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.Broker;
@@ -40,6 +43,8 @@ import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+
/**
*
*/
@@ -49,6 +54,7 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
private static AbstractCachingSchemaSourceProvider GLOBAL_NETCONF_SOURCE_PROVIDER = null;
private BundleContext bundleContext;
+ private Optional userCapabilities;
public NetconfConnectorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
@@ -82,9 +88,11 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
checkNotNull(getPassword(), passwordJmxAttribute);
}
+ userCapabilities = getUserCapabilities();
+
}
- private boolean isHostAddressPresent(Host address) {
+ private boolean isHostAddressPresent(final Host address) {
return address.getDomainName() != null ||
address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
}
@@ -98,10 +106,14 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
final Broker domBroker = getDomRegistryDependency();
final BindingAwareBroker bindingBroker = getBindingRegistryDependency();
- final RemoteDeviceHandler salFacade = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor);
+ final RemoteDeviceHandler salFacade
+ = new NetconfDeviceSalFacade(id, domBroker, bindingBroker, bundleContext, globalProcessingExecutor);
final NetconfDevice device =
NetconfDevice.createNetconfDevice(id, getGlobalNetconfSchemaProvider(), globalProcessingExecutor, salFacade);
- final NetconfDeviceCommunicator listener = new NetconfDeviceCommunicator(id, device);
+
+ final NetconfDeviceCommunicator listener = userCapabilities.isPresent() ?
+ new NetconfDeviceCommunicator(id, device, userCapabilities.get()) : new NetconfDeviceCommunicator(id, device);
+
final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(listener);
final NetconfClientDispatcher dispatcher = getClientDispatcherDependency();
@@ -116,6 +128,26 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
};
}
+ private Optional getUserCapabilities() {
+ if(getYangModuleCapabilities() == null) {
+ return Optional.absent();
+ }
+
+ final List capabilities = getYangModuleCapabilities().getCapability();
+ if(capabilities == null || capabilities.isEmpty()) {
+ return Optional.absent();
+ }
+
+ final NetconfSessionCapabilities parsedOverrideCapabilities = NetconfSessionCapabilities.fromStrings(capabilities);
+ JmxAttributeValidationException.checkCondition(
+ parsedOverrideCapabilities.getNonModuleCaps().isEmpty(),
+ "Capabilities to override can only contain module based capabilities, non-module capabilities will be retrieved from the device," +
+ " configured non-module capabilities: " + parsedOverrideCapabilities.getNonModuleCaps(),
+ yangModuleCapabilitiesJmxAttribute);
+
+ return Optional.of(parsedOverrideCapabilities);
+ }
+
private synchronized AbstractCachingSchemaSourceProvider getGlobalNetconfSchemaProvider() {
if(GLOBAL_NETCONF_SOURCE_PROVIDER == null) {
final String storageFile = "cache/schema";
@@ -175,8 +207,8 @@ public final class NetconfConnectorModule extends org.opendaylight.controller.co
if(getAddress().getDomainName() != null) {
return new InetSocketAddress(getAddress().getDomainName().getValue(), getPort().getValue());
} else {
- IpAddress ipAddress = getAddress().getIpAddress();
- String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
+ final IpAddress ipAddress = getAddress().getIpAddress();
+ final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
return new InetSocketAddress(ip, getPort().getValue());
}
}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
index de4ac7ac18..07d3c08774 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.java
@@ -118,6 +118,7 @@ public final class NetconfDevice implements RemoteDevice {
private static final Logger logger = LoggerFactory.getLogger(NetconfDeviceCommunicator.class);
private final RemoteDevice remoteDevice;
+ private final Optional overrideNetconfCapabilities;
private final RemoteDeviceId id;
private final Lock sessionLock = new ReentrantLock();
+ private final Queue requests = new ArrayDeque<>();
+ private NetconfClientSession session;
+
+ public NetconfDeviceCommunicator(final RemoteDeviceId id, final RemoteDevice remoteDevice,
+ final NetconfSessionCapabilities netconfSessionCapabilities) {
+ this(id, remoteDevice, Optional.of(netconfSessionCapabilities));
+ }
+
public NetconfDeviceCommunicator(final RemoteDeviceId id,
- final RemoteDevice remoteDevice) {
+ final RemoteDevice remoteDevice) {
+ this(id, remoteDevice, Optional.absent());
+ }
+
+ private NetconfDeviceCommunicator(final RemoteDeviceId id, final RemoteDevice remoteDevice,
+ final Optional overrideNetconfCapabilities) {
this.id = id;
this.remoteDevice = remoteDevice;
+ this.overrideNetconfCapabilities = overrideNetconfCapabilities;
}
- private final Queue requests = new ArrayDeque<>();
- private NetconfClientSession session;
-
@Override
public void onSessionUp(final NetconfClientSession session) {
sessionLock.lock();
@@ -68,10 +78,15 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
logger.debug("{}: Session established", id);
this.session = session;
- final NetconfSessionCapabilities netconfSessionCapabilities =
+ NetconfSessionCapabilities netconfSessionCapabilities =
NetconfSessionCapabilities.fromNetconfSession(session);
logger.trace("{}: Session advertised capabilities: {}", id, netconfSessionCapabilities);
+ if(overrideNetconfCapabilities.isPresent()) {
+ netconfSessionCapabilities = netconfSessionCapabilities.replaceModuleCaps(overrideNetconfCapabilities.get());
+ logger.debug("{}: Session capabilities overridden, capabilities that will be used: {}", id, netconfSessionCapabilities);
+ }
+
remoteDevice.onRemoteSessionUp(netconfSessionCapabilities, this);
}
finally {
@@ -223,7 +238,7 @@ public class NetconfDeviceCommunicator implements NetconfClientSessionListener,
return;
}
- request.future.set( RpcResultBuilder.success( message ).build() );
+ request.future.set( RpcResultBuilder.success( message ).build() );
}
}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java
index 8964a80228..1a7d90e9c0 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilities.java
@@ -8,6 +8,7 @@ import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -19,6 +20,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class NetconfSessionCapabilities {
+
private static final class ParameterMatcher {
private final Predicate predicate;
private final int skipLength;
@@ -57,10 +59,10 @@ public final class NetconfSessionCapabilities {
};
private final Set moduleBasedCaps;
- private final Set capabilities;
+ private final Set nonModuleCaps;
- private NetconfSessionCapabilities(final Set capabilities, final Set moduleBasedCaps) {
- this.capabilities = Preconditions.checkNotNull(capabilities);
+ private NetconfSessionCapabilities(final Set nonModuleCaps, final Set moduleBasedCaps) {
+ this.nonModuleCaps = Preconditions.checkNotNull(nonModuleCaps);
this.moduleBasedCaps = Preconditions.checkNotNull(moduleBasedCaps);
}
@@ -68,30 +70,49 @@ public final class NetconfSessionCapabilities {
return moduleBasedCaps;
}
- public boolean containsCapability(final String capability) {
- return capabilities.contains(capability);
+ public Set getNonModuleCaps() {
+ return nonModuleCaps;
+ }
+
+ public boolean containsNonModuleCapability(final String capability) {
+ return nonModuleCaps.contains(capability);
}
- public boolean containsCapability(final QName capability) {
+ public boolean containsModuleCapability(final QName capability) {
return moduleBasedCaps.contains(capability);
}
@Override
public String toString() {
return Objects.toStringHelper(this)
- .add("capabilities", capabilities)
+ .add("capabilities", nonModuleCaps)
+ .add("moduleBasedCapabilities", moduleBasedCaps)
.add("rollback", isRollbackSupported())
.add("monitoring", isMonitoringSupported())
.toString();
}
public boolean isRollbackSupported() {
- return containsCapability(NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
+ return containsNonModuleCapability(NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
+ }
+
+ public boolean isCandidateSupported() {
+ return containsNonModuleCapability(NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString());
}
public boolean isMonitoringSupported() {
- return containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)
- || containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
+ return containsModuleCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)
+ || containsNonModuleCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
+ }
+
+ public NetconfSessionCapabilities replaceModuleCaps(final NetconfSessionCapabilities netconfSessionModuleCapabilities) {
+ final Set moduleBasedCaps = Sets.newHashSet(netconfSessionModuleCapabilities.getModuleBasedCaps());
+
+ // Preserve monitoring module, since it indicates support for ietf-netconf-monitoring
+ if(containsModuleCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)) {
+ moduleBasedCaps.add(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING);
+ }
+ return new NetconfSessionCapabilities(getNonModuleCaps(), moduleBasedCaps);
}
public static NetconfSessionCapabilities fromNetconfSession(final NetconfClientSession session) {
@@ -100,6 +121,7 @@ public final class NetconfSessionCapabilities {
public static NetconfSessionCapabilities fromStrings(final Collection capabilities) {
final Set moduleBasedCaps = new HashSet<>();
+ final Set nonModuleCaps = Sets.newHashSet(capabilities);
for (final String capability : capabilities) {
final int qmark = capability.indexOf('?');
@@ -117,6 +139,7 @@ public final class NetconfSessionCapabilities {
String revision = REVISION_PARAM.from(queryParams);
if (revision != null) {
moduleBasedCaps.add(QName.create(namespace, revision, moduleName));
+ nonModuleCaps.remove(capability);
continue;
}
@@ -136,8 +159,9 @@ public final class NetconfSessionCapabilities {
// FIXME: do we really want to continue here?
moduleBasedCaps.add(QName.create(namespace, revision, moduleName));
+ nonModuleCaps.remove(capability);
}
- return new NetconfSessionCapabilities(ImmutableSet.copyOf(capabilities), ImmutableSet.copyOf(moduleBasedCaps));
+ return new NetconfSessionCapabilities(ImmutableSet.copyOf(nonModuleCaps), ImmutableSet.copyOf(moduleBasedCaps));
}
}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceDataBroker.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceDataBroker.java
index ee0c8b7217..f3a9acd630 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceDataBroker.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceDataBroker.java
@@ -42,7 +42,7 @@ final class NetconfDeviceDataBroker implements DOMDataBroker {
@Override
public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
- return new NetconfDeviceReadOnlyTx(rpc, normalizer);
+ return new NetconfDeviceReadOnlyTx(rpc, normalizer, id);
}
@Override
@@ -52,8 +52,7 @@ final class NetconfDeviceDataBroker implements DOMDataBroker {
@Override
public DOMDataWriteTransaction newWriteOnlyTransaction() {
- // FIXME detect if candidate is supported, true is hardcoded
- return new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, true, netconfSessionPreferences.isRollbackSupported());
+ return new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, netconfSessionPreferences.isCandidateSupported(), netconfSessionPreferences.isRollbackSupported());
}
@Override
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java
index 3248453baf..9ef44f6584 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java
@@ -15,6 +15,7 @@ import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessag
import com.google.common.base.Function;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -22,6 +23,7 @@ import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizat
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -32,16 +34,19 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+
public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction {
private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceReadOnlyTx.class);
private final RpcImplementation rpc;
private final DataNormalizer normalizer;
+ private final RemoteDeviceId id;
- public NetconfDeviceReadOnlyTx(final RpcImplementation rpc, final DataNormalizer normalizer) {
+ public NetconfDeviceReadOnlyTx(final RpcImplementation rpc, final DataNormalizer normalizer, final RemoteDeviceId id) {
this.rpc = rpc;
this.normalizer = normalizer;
+ this.id = id;
}
public ListenableFuture>> readConfigurationData(final YangInstanceIdentifier path) {
@@ -51,6 +56,8 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
return Futures.transform(future, new Function, Optional>>() {
@Override
public Optional> apply(final RpcResult result) {
+ checkReadSuccess(result, path);
+
final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
final CompositeNode node = (CompositeNode) findNode(data, path);
@@ -61,6 +68,11 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
});
}
+ private void checkReadSuccess(final RpcResult result, final YangInstanceIdentifier path) {
+ LOG.warn("{}: Unable to read data: {}, errors: {}", id, path, result.getErrors());
+ Preconditions.checkArgument(result.isSuccessful(), "%s: Unable to read data: %s, errors: %s", id, path, result.getErrors());
+ }
+
private Optional> transform(final YangInstanceIdentifier path, final CompositeNode node) {
if(node == null) {
return Optional.absent();
@@ -68,7 +80,7 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
try {
return Optional.>of(normalizer.toNormalized(path, node).getValue());
} catch (final Exception e) {
- LOG.error("Unable to normalize data for {}, data: {}", path, node, e);
+ LOG.error("{}: Unable to normalize data for {}, data: {}", id, path, node, e);
throw e;
}
}
@@ -79,6 +91,8 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
return Futures.transform(future, new Function, Optional>>() {
@Override
public Optional> apply(final RpcResult result) {
+ checkReadSuccess(result, path);
+
final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
final CompositeNode node = (CompositeNode) findNode(data, path);
@@ -123,7 +137,7 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
@Override
public ListenableFuture>> read(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
- final YangInstanceIdentifier legacyPath = toLegacyPath(normalizer, path);
+ final YangInstanceIdentifier legacyPath = toLegacyPath(normalizer, path, id);
switch (store) {
case CONFIGURATION : {
@@ -134,14 +148,14 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
}
}
- throw new IllegalArgumentException(String.format("Cannot read data %s for %s datastore, unknown datastore type", path, store));
+ throw new IllegalArgumentException(String.format("%s, Cannot read data %s for %s datastore, unknown datastore type", id, path, store));
}
- static YangInstanceIdentifier toLegacyPath(final DataNormalizer normalizer, final YangInstanceIdentifier path) {
+ static YangInstanceIdentifier toLegacyPath(final DataNormalizer normalizer, final YangInstanceIdentifier path, final RemoteDeviceId id) {
try {
return normalizer.toLegacy(path);
} catch (final DataNormalizationException e) {
- throw new IllegalArgumentException("Cannot normalize path " + path, e);
+ throw new IllegalArgumentException(id + ": Cannot normalize path " + path, e);
}
}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTx.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTx.java
index c8d9028210..87f5477d35 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTx.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTx.java
@@ -8,10 +8,11 @@
package org.opendaylight.controller.sal.connect.netconf.sal.tx;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.DISCARD_CHANGES_RPC_CONTENT;
import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME;
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CONFIG_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DEFAULT_OPERATION_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_ERROR_OPTION_QNAME;
import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_OPERATION_QNAME;
@@ -26,13 +27,14 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
-import javax.annotation.Nullable;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
@@ -57,97 +59,114 @@ import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
+public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction, FutureCallback> {
private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceWriteOnlyTx.class);
private final RemoteDeviceId id;
private final RpcImplementation rpc;
private final DataNormalizer normalizer;
+
private final boolean rollbackSupported;
+ private final boolean candidateSupported;
private final CompositeNode targetNode;
+ // Allow commit to be called only once
+ private final AtomicBoolean finished = new AtomicBoolean(false);
+
public NetconfDeviceWriteOnlyTx(final RemoteDeviceId id, final RpcImplementation rpc, final DataNormalizer normalizer, final boolean candidateSupported, final boolean rollbackOnErrorSupported) {
this.id = id;
this.rpc = rpc;
this.normalizer = normalizer;
- this.targetNode = getTargetNode(candidateSupported);
+
+ this.candidateSupported = candidateSupported;
+ this.targetNode = getTargetNode(this.candidateSupported);
this.rollbackSupported = rollbackOnErrorSupported;
}
- // FIXME add logging
-
@Override
public boolean cancel() {
- if(isCommitted()) {
+ if(isFinished()) {
return false;
}
return discardChanges();
}
- private boolean isCommitted() {
- // TODO 732
- return true;
+ private boolean isFinished() {
+ return finished.get();
}
private boolean discardChanges() {
- // TODO 732
+ finished.set(true);
+
+ if(candidateSupported) {
+ sendDiscardChanges();
+ }
return true;
}
// TODO should the edit operations be blocking ?
+ // TODO should the discard-changes operations be blocking ?
@Override
public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode, ?> data) {
+ checkNotFinished();
Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can merge only configuration, not %s", store);
try {
- final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path);
+ final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path, id);
final CompositeNode legacyData = normalizer.toLegacy(path, data);
- sendEditRpc(createEditConfigStructure(legacyPath, Optional.of(ModifyAction.REPLACE), Optional.fromNullable(legacyData)), Optional.of(ModifyAction.NONE));
+ sendEditRpc(
+ createEditConfigStructure(legacyPath, Optional.of(ModifyAction.REPLACE), Optional.fromNullable(legacyData)), Optional.of(ModifyAction.NONE));
} catch (final ExecutionException e) {
- LOG.warn("Error putting data to {}, data: {}, discarding changes", path, data, e);
+ LOG.warn("{}: Error putting data to {}, data: {}, discarding changes", id, path, data, e);
discardChanges();
- throw new RuntimeException("Error while replacing " + path, e);
+ throw new RuntimeException(id + ": Error while replacing " + path, e);
}
}
+ private void checkNotFinished() {
+ Preconditions.checkState(isFinished() == false, "%s: Transaction %s already finished", id, getIdentifier());
+ }
+
@Override
public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode, ?> data) {
- Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can merge only configuration, not %s", store);
+ checkNotFinished();
+ Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "%s: Can merge only configuration, not %s", id, store);
try {
- final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path);
+ final YangInstanceIdentifier legacyPath = NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path, id);
final CompositeNode legacyData = normalizer.toLegacy(path, data);
sendEditRpc(
createEditConfigStructure(legacyPath, Optional. absent(), Optional.fromNullable(legacyData)), Optional. absent());
} catch (final ExecutionException e) {
- LOG.warn("Error merging data to {}, data: {}, discarding changes", path, data, e);
+ LOG.warn("{}: Error merging data to {}, data: {}, discarding changes", id, path, data, e);
discardChanges();
- throw new RuntimeException("Error while merging " + path, e);
+ throw new RuntimeException(id + ": Error while merging " + path, e);
}
}
@Override
public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
- Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can merge only configuration, not %s", store);
+ checkNotFinished();
+ Preconditions.checkArgument(store == LogicalDatastoreType.CONFIGURATION, "%s: Can merge only configuration, not %s", id, store);
try {
- sendEditRpc(createEditConfigStructure(NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path), Optional.of(ModifyAction.DELETE), Optional.absent()), Optional.of(ModifyAction.NONE));
+ sendEditRpc(
+ createEditConfigStructure(NetconfDeviceReadOnlyTx.toLegacyPath(normalizer, path, id), Optional.of(ModifyAction.DELETE), Optional.absent()), Optional.of(ModifyAction.NONE));
} catch (final ExecutionException e) {
- LOG.warn("Error deleting data {}, discarding changes", path, e);
+ LOG.warn("{}: Error deleting data {}, discarding changes", id, path, e);
discardChanges();
- throw new RuntimeException("Error while deleting " + path, e);
+ throw new RuntimeException(id + ": Error while deleting " + path, e);
}
}
@Override
public CheckedFuture submit() {
final ListenableFuture commmitFutureAsVoid = Futures.transform(commit(), new Function, Void>() {
- @Nullable
@Override
- public Void apply(@Nullable final RpcResult input) {
+ public Void apply(final RpcResult input) {
return null;
}
});
@@ -162,25 +181,46 @@ public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
@Override
public ListenableFuture> commit() {
- // FIXME do not allow commit if closed or failed
+ checkNotFinished();
+ finished.set(true);
- final ListenableFuture> rpcResult = rpc.invokeRpc(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME, getCommitRequest());
- return Futures.transform(rpcResult, new Function, RpcResult>() {
- @Override
- public RpcResult apply(@Nullable final RpcResult input) {
- if(input.isSuccessful()) {
- return RpcResultBuilder.success(TransactionStatus.COMMITED).build();
- } else {
- final RpcResultBuilder failed = RpcResultBuilder.failed();
- for (final RpcError rpcError : input.getErrors()) {
- failed.withError(rpcError.getErrorType(), rpcError.getTag(), rpcError.getMessage(), rpcError.getApplicationTag(), rpcError.getInfo(), rpcError.getCause());
+ if(candidateSupported == false) {
+ return Futures.immediateFuture(RpcResultBuilder.success(TransactionStatus.COMMITED).build());
+ }
+
+ final ListenableFuture> rpcResult = rpc.invokeRpc(
+ NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME, NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
+
+ final ListenableFuture> transformed = Futures.transform(rpcResult,
+ new Function, RpcResult>() {
+ @Override
+ public RpcResult apply(final RpcResult input) {
+ if (input.isSuccessful()) {
+ return RpcResultBuilder.success(TransactionStatus.COMMITED).build();
+ } else {
+ final RpcResultBuilder failed = RpcResultBuilder.failed();
+ for (final RpcError rpcError : input.getErrors()) {
+ failed.withError(rpcError.getErrorType(), rpcError.getTag(), rpcError.getMessage(),
+ rpcError.getApplicationTag(), rpcError.getInfo(), rpcError.getCause());
+ }
+ return failed.build();
+ }
}
- return failed.build();
- }
- }
- });
+ });
- // FIXME 732 detect commit failure
+ Futures.addCallback(transformed, this);
+ return transformed;
+ }
+
+ @Override
+ public void onSuccess(final RpcResult result) {
+ LOG.debug("{}: Write successful, transaction: {}", id, getIdentifier());
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.warn("{}: Write failed, transaction {}, discarding changes", id, getIdentifier(), t);
+ discardChanges();
}
private void sendEditRpc(final CompositeNode editStructure, final Optional defaultOperation) throws ExecutionException {
@@ -200,6 +240,22 @@ public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
}
}
+ private void sendDiscardChanges() {
+ final ListenableFuture> discardFuture = rpc.invokeRpc(NETCONF_DISCARD_CHANGES_QNAME, DISCARD_CHANGES_RPC_CONTENT);
+ Futures.addCallback(discardFuture, new FutureCallback>() {
+ @Override
+ public void onSuccess(final RpcResult result) {
+ LOG.debug("{}: Discarding transaction: {}", id, getIdentifier());
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ LOG.error("{}: Discarding changes failed, transaction: {}. Device configuration might be corrupted", id, getIdentifier(), t);
+ throw new RuntimeException(id + ": Discarding changes failed, transaction " + getIdentifier(), t);
+ }
+ });
+ }
+
private CompositeNode createEditConfigStructure(final YangInstanceIdentifier dataPath, final Optional operation,
final Optional lastChildOverride) {
Preconditions.checkArgument(Iterables.isEmpty(dataPath.getPathArguments()) == false, "Instance identifier with empty path %s", dataPath);
@@ -298,13 +354,6 @@ public class NetconfDeviceWriteOnlyTx implements DOMDataWriteTransaction {
}
}
- private ImmutableCompositeNode getCommitRequest() {
- final CompositeNodeBuilder commitInput = ImmutableCompositeNode.builder();
- commitInput.setQName(NETCONF_COMMIT_QNAME);
- return commitInput.toInstance();
- }
-
-
@Override
public Object getIdentifier() {
return this;
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
index a6924d9d37..d3faddd471 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java
@@ -35,6 +35,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -45,8 +46,7 @@ import org.w3c.dom.Element;
public class NetconfMessageTransformUtil {
- private NetconfMessageTransformUtil() {
- }
+ private NetconfMessageTransformUtil() {}
public static final QName IETF_NETCONF_MONITORING = QName.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "ietf-netconf-monitoring");
public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
@@ -66,14 +66,27 @@ public class NetconfMessageTransformUtil {
public static QName NETCONF_DEFAULT_OPERATION_QNAME = QName.create(NETCONF_OPERATION_QNAME, "default-operation");
public static QName NETCONF_EDIT_CONFIG_QNAME = QName.create(NETCONF_QNAME, "edit-config");
public static QName NETCONF_GET_CONFIG_QNAME = QName.create(NETCONF_QNAME, "get-config");
+ public static QName NETCONF_DISCARD_CHANGES_QNAME = QName.create(NETCONF_QNAME, "discard-changes");
public static QName NETCONF_TYPE_QNAME = QName.create(NETCONF_QNAME, "type");
public static QName NETCONF_FILTER_QNAME = QName.create(NETCONF_QNAME, "filter");
public static QName NETCONF_GET_QNAME = QName.create(NETCONF_QNAME, "get");
public static QName NETCONF_RPC_QNAME = QName.create(NETCONF_QNAME, "rpc");
+
public static URI NETCONF_ROLLBACK_ON_ERROR_URI = URI
.create("urn:ietf:params:netconf:capability:rollback-on-error:1.0");
public static String ROLLBACK_ON_ERROR_OPTION = "rollback-on-error";
+ public static URI NETCONF_CANDIDATE_URI = URI
+ .create("urn:ietf:params:netconf:capability:candidate:1.0");
+
+ // Discard changes message
+ public static final CompositeNode DISCARD_CHANGES_RPC_CONTENT =
+ NodeFactory.createImmutableCompositeNode(NETCONF_DISCARD_CHANGES_QNAME, null, Collections.>emptyList());
+
+ // Commit changes message
+ public static final CompositeNode COMMIT_RPC_CONTENT =
+ NodeFactory.createImmutableCompositeNode(NETCONF_COMMIT_QNAME, null, Collections.>emptyList());
+
public static Node> toFilterStructure(final YangInstanceIdentifier identifier) {
Node> previous = null;
if (Iterables.isEmpty(identifier.getPathArguments())) {
@@ -269,5 +282,4 @@ public class NetconfMessageTransformUtil {
return it.toInstance();
}
}
-
}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang
index 6bad4798c2..e13398b1df 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang
+++ b/opendaylight/md-sal/sal-netconf-connector/src/main/yang/odl-sal-netconf-connector-cfg.yang
@@ -58,6 +58,14 @@ module odl-sal-netconf-connector-cfg {
type string;
}
+ container yang-module-capabilities {
+ leaf-list capability {
+ type string;
+ description "Set a list of capabilities to override capabilities provided in device's hello message.
+ Can be used for devices that do not report any yang modules in their hello message";
+ }
+ }
+
container dom-registry {
uses config:service-ref {
refine type {
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
index 391bf9c6a4..001b9a8d3a 100644
--- a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
+++ b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java
@@ -8,35 +8,35 @@
package org.opendaylight.controller.sal.connect.netconf.listener;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
+import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.ListenableFuture;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
-
import java.io.ByteArrayInputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
-import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
-
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
@@ -56,10 +56,6 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.ListenableFuture;
-
public class NetconfDeviceCommunicatorTest {
@Mock
@@ -129,9 +125,9 @@ public class NetconfDeviceCommunicatorTest {
verify( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
NetconfSessionCapabilities actualCapabilites = netconfSessionCapabilities.getValue();
- assertEquals( "containsCapability", true, actualCapabilites.containsCapability(
- NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString() ) );
- assertEquals( "containsCapability", true, actualCapabilites.containsCapability( testCapability ) );
+ assertEquals( "containsModuleCapability", true, actualCapabilites.containsNonModuleCapability(
+ NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString()) );
+ assertEquals( "containsModuleCapability", false, actualCapabilites.containsNonModuleCapability(testCapability) );
assertEquals( "getModuleBasedCaps", Sets.newHashSet(
QName.create( "urn:opendaylight:params:xml:ns:test", "2014-06-02", "test-module" )),
actualCapabilites.getModuleBasedCaps() );
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilitiesTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilitiesTest.java
new file mode 100644
index 0000000000..87947b57fa
--- /dev/null
+++ b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/listener/NetconfSessionCapabilitiesTest.java
@@ -0,0 +1,50 @@
+package org.opendaylight.controller.sal.connect.netconf.listener;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public class NetconfSessionCapabilitiesTest {
+
+ @Test
+ public void testMerge() throws Exception {
+ final List caps1 = Lists.newArrayList(
+ "namespace:1?module=module1&revision=2012-12-12",
+ "namespace:2?module=module2&revision=2012-12-12",
+ "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04",
+ "urn:ietf:params:netconf:base:1.0",
+ "urn:ietf:params:netconf:capability:rollback-on-error:1.0"
+ );
+ final NetconfSessionCapabilities sessionCaps1 = NetconfSessionCapabilities.fromStrings(caps1);
+ assertCaps(sessionCaps1, 2, 3);
+
+ final List caps2 = Lists.newArrayList(
+ "namespace:3?module=module3&revision=2012-12-12",
+ "namespace:4?module=module4&revision=2012-12-12",
+ "randomNonModuleCap"
+ );
+ final NetconfSessionCapabilities sessionCaps2 = NetconfSessionCapabilities.fromStrings(caps2);
+ assertCaps(sessionCaps2, 1, 2);
+
+ final NetconfSessionCapabilities merged = sessionCaps1.replaceModuleCaps(sessionCaps2);
+ assertCaps(merged, 2, 2 + 1 /*Preserved monitoring*/);
+ for (final QName qName : sessionCaps2.getModuleBasedCaps()) {
+ assertThat(merged.getModuleBasedCaps(), JUnitMatchers.hasItem(qName));
+ }
+ assertThat(merged.getModuleBasedCaps(), JUnitMatchers.hasItem(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING));
+
+ assertThat(merged.getNonModuleCaps(), JUnitMatchers.hasItem("urn:ietf:params:netconf:base:1.0"));
+ assertThat(merged.getNonModuleCaps(), JUnitMatchers.hasItem("urn:ietf:params:netconf:capability:rollback-on-error:1.0"));
+ }
+
+ private void assertCaps(final NetconfSessionCapabilities sessionCaps1, final int nonModuleCaps, final int moduleCaps) {
+ assertEquals(nonModuleCaps, sessionCaps1.getNonModuleCaps().size());
+ assertEquals(moduleCaps, sessionCaps1.getModuleBasedCaps().size());
+ }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java
new file mode 100644
index 0000000000..a65e426d59
--- /dev/null
+++ b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceWriteOnlyTxTest.java
@@ -0,0 +1,79 @@
+package org.opendaylight.controller.sal.connect.netconf.sal.tx;
+
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.DISCARD_CHANGES_RPC_CONTENT;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class NetconfDeviceWriteOnlyTxTest {
+
+ private final RemoteDeviceId id = new RemoteDeviceId("test-mount");
+
+ @Mock
+ private RpcImplementation rpc;
+ @Mock
+ private DataNormalizer normalizer;
+ private YangInstanceIdentifier yangIId;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ doReturn(Futures.>immediateFailedFuture(new IllegalStateException("Failed tx")))
+ .doReturn(Futures.immediateFuture(RpcResultBuilder.success().build()))
+ .when(rpc).invokeRpc(any(QName.class), any(CompositeNode.class));
+
+ yangIId = YangInstanceIdentifier.builder().node(QName.create("namespace", "2012-12-12", "name")).build();
+ doReturn(yangIId).when(normalizer).toLegacy(yangIId);
+ }
+
+ @Test
+ public void testDiscardCahnges() {
+ final NetconfDeviceWriteOnlyTx tx = new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, true, true);
+ final CheckedFuture submitFuture = tx.submit();
+ try {
+ submitFuture.checkedGet();
+ } catch (final TransactionCommitFailedException e) {
+ // verify discard changes was sent
+ verify(rpc).invokeRpc(NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME, DISCARD_CHANGES_RPC_CONTENT);
+ return;
+ }
+
+ fail("Submit should fail");
+ }
+
+
+ @Test
+ public void testDiscardCahngesNotSentWithoutCandidate() {
+ doReturn(Futures.immediateFuture(RpcResultBuilder.success().build()))
+ .doReturn(Futures.>immediateFailedFuture(new IllegalStateException("Failed tx")))
+ .when(rpc).invokeRpc(any(QName.class), any(CompositeNode.class));
+
+ final NetconfDeviceWriteOnlyTx tx = new NetconfDeviceWriteOnlyTx(id, rpc, normalizer, false, true);
+ tx.delete(LogicalDatastoreType.CONFIGURATION, yangIId);
+ verify(rpc).invokeRpc(eq(NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME), any(CompositeNode.class));
+ verifyNoMoreInteractions(rpc);
+ }
+
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml b/opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml
index e3fac63a83..28e629a92c 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/pom.xml
@@ -114,6 +114,13 @@
org.opendaylight.yangtoolsyang-binding
+
+
+ org.opendaylight.controller
+ sal-akka-raft
+ 1.1-SNAPSHOT
+
+
com.google.guavaguava
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java
new file mode 100644
index 0000000000..87b246bd7e
--- /dev/null
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/mdsal/CompositeModificationPayload.java
@@ -0,0 +1,60 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: CompositeModificationPayload.proto
+
+package org.opendaylight.controller.mdsal;
+
+public final class CompositeModificationPayload {
+ private CompositeModificationPayload() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ registry.add(org.opendaylight.controller.mdsal.CompositeModificationPayload.modification);
+ }
+ public static final int MODIFICATION_FIELD_NUMBER = 2;
+ /**
+ * extend .org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload { ... }
+ */
+ public static final
+ com.google.protobuf.GeneratedMessage.GeneratedExtension<
+ org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.AppendEntries.ReplicatedLogEntry.Payload,
+ org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.CompositeModification> modification = com.google.protobuf.GeneratedMessage
+ .newFileScopedGeneratedExtension(
+ org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.CompositeModification.class,
+ org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.CompositeModification.getDefaultInstance());
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\"CompositeModificationPayload.proto\022!or" +
+ "g.opendaylight.controller.mdsal\032\033AppendE" +
+ "ntriesMessages.proto\032\014Common.proto\032\020Pers" +
+ "istent.proto:\242\001\n\014modification\022R.org.open" +
+ "daylight.controller.cluster.raft.AppendE" +
+ "ntries.ReplicatedLogEntry.Payload\030\002 \001(\0132" +
+ "8.org.opendaylight.controller.mdsal.Comp" +
+ "ositeModification"
+ };
+ com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+ new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ modification.internalInit(descriptor.getExtensions().get(0));
+ return null;
+ }
+ };
+ com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(),
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.getDescriptor(),
+ org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.getDescriptor(),
+ }, assigner);
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java
index 22a93c0e10..ac0701a6d8 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/cohort3pc/ThreePhaseCommitCohortMessages.java
@@ -652,7 +652,7 @@ public final class ThreePhaseCommitCohortMessages {
public final boolean isInitialized() {
if (!hasCanCommit()) {
-
+
return false;
}
return true;
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java
index 35c2940be3..81e5b462cc 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/NormalizedNodeMessages.java
@@ -179,7 +179,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -195,7 +195,7 @@ public final class NormalizedNodeMessages {
getNameBytes() {
java.lang.Object ref = name_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
name_ = b;
@@ -222,7 +222,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -238,7 +238,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -265,7 +265,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -281,7 +281,7 @@ public final class NormalizedNodeMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -541,7 +541,7 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
if (!hasName()) {
-
+
return false;
}
return true;
@@ -595,7 +595,7 @@ public final class NormalizedNodeMessages {
getNameBytes() {
java.lang.Object ref = name_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
name_ = b;
@@ -669,7 +669,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -743,7 +743,7 @@ public final class NormalizedNodeMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -930,7 +930,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -946,7 +946,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -1168,7 +1168,7 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
if (!hasValue()) {
-
+
return false;
}
return true;
@@ -1222,7 +1222,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -1341,7 +1341,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
*/
- java.util.List
+ java.util.List
getAttributesList();
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
@@ -1354,7 +1354,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
@@ -1504,7 +1504,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1520,7 +1520,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -1555,7 +1555,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1575,7 +1575,7 @@ public final class NormalizedNodeMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -1619,7 +1619,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesOrBuilderList() {
return attributes_;
}
@@ -1948,7 +1948,7 @@ public final class NormalizedNodeMessages {
attributesBuilder_ = null;
attributes_ = other.attributes_;
bitField0_ = (bitField0_ & ~0x00000008);
- attributesBuilder_ =
+ attributesBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getAttributesFieldBuilder() : null;
} else {
@@ -1962,18 +1962,18 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
if (!hasValue()) {
-
+
return false;
}
if (hasNodeType()) {
if (!getNodeType().isInitialized()) {
-
+
return false;
}
}
for (int i = 0; i < getAttributesCount(); i++) {
if (!getAttributes(i).isInitialized()) {
-
+
return false;
}
}
@@ -2028,7 +2028,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -2114,7 +2114,7 @@ public final class NormalizedNodeMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -2275,7 +2275,7 @@ public final class NormalizedNodeMessages {
* optional .org.opendaylight.controller.mdsal.QName nodeType = 3;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QName.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.QNameOrBuilder>
getNodeTypeFieldBuilder() {
if (nodeTypeBuilder_ == null) {
nodeTypeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -2483,7 +2483,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesOrBuilderList() {
if (attributesBuilder_ != null) {
return attributesBuilder_.getMessageOrBuilderList();
@@ -2509,12 +2509,12 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 4;
*/
- public java.util.List
+ public java.util.List
getAttributesBuilderList() {
return getAttributesFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesFieldBuilder() {
if (attributesBuilder_ == null) {
attributesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -2546,7 +2546,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
*/
- java.util.List
+ java.util.List
getArgumentsList();
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
@@ -2559,7 +2559,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
getArgumentsOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
@@ -2680,7 +2680,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
getArgumentsOrBuilderList() {
return arguments_;
}
@@ -2933,7 +2933,7 @@ public final class NormalizedNodeMessages {
argumentsBuilder_ = null;
arguments_ = other.arguments_;
bitField0_ = (bitField0_ & ~0x00000001);
- argumentsBuilder_ =
+ argumentsBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getArgumentsFieldBuilder() : null;
} else {
@@ -2948,7 +2948,7 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
for (int i = 0; i < getArgumentsCount(); i++) {
if (!getArguments(i).isInitialized()) {
-
+
return false;
}
}
@@ -3169,7 +3169,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
getArgumentsOrBuilderList() {
if (argumentsBuilder_ != null) {
return argumentsBuilder_.getMessageOrBuilderList();
@@ -3195,12 +3195,12 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.PathArgument arguments = 1;
*/
- public java.util.List
+ public java.util.List
getArgumentsBuilderList() {
return getArgumentsFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgument.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.PathArgumentOrBuilder>
getArgumentsFieldBuilder() {
if (argumentsBuilder_ == null) {
argumentsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -3262,7 +3262,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
*/
- java.util.List
+ java.util.List
getAttributesList();
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
@@ -3275,7 +3275,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
@@ -3287,7 +3287,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
*/
- java.util.List
+ java.util.List
getChildList();
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
@@ -3300,7 +3300,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getChildOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
@@ -3546,7 +3546,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -3562,7 +3562,7 @@ public final class NormalizedNodeMessages {
getPathBytes() {
java.lang.Object ref = path_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
path_ = b;
@@ -3589,7 +3589,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -3605,7 +3605,7 @@ public final class NormalizedNodeMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -3627,7 +3627,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesOrBuilderList() {
return attributes_;
}
@@ -3663,7 +3663,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getChildOrBuilderList() {
return child_;
}
@@ -3704,7 +3704,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -3720,7 +3720,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -3747,7 +3747,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -3763,7 +3763,7 @@ public final class NormalizedNodeMessages {
getValueTypeBytes() {
java.lang.Object ref = valueType_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
valueType_ = b;
@@ -4202,7 +4202,7 @@ public final class NormalizedNodeMessages {
attributesBuilder_ = null;
attributes_ = other.attributes_;
bitField0_ = (bitField0_ & ~0x00000004);
- attributesBuilder_ =
+ attributesBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getAttributesFieldBuilder() : null;
} else {
@@ -4228,7 +4228,7 @@ public final class NormalizedNodeMessages {
childBuilder_ = null;
child_ = other.child_;
bitField0_ = (bitField0_ & ~0x00000008);
- childBuilder_ =
+ childBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getChildFieldBuilder() : null;
} else {
@@ -4266,19 +4266,19 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
for (int i = 0; i < getAttributesCount(); i++) {
if (!getAttributes(i).isInitialized()) {
-
+
return false;
}
}
for (int i = 0; i < getChildCount(); i++) {
if (!getChild(i).isInitialized()) {
-
+
return false;
}
}
if (hasInstanceIdentifierValue()) {
if (!getInstanceIdentifierValue().isInitialized()) {
-
+
return false;
}
}
@@ -4333,7 +4333,7 @@ public final class NormalizedNodeMessages {
getPathBytes() {
java.lang.Object ref = path_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
path_ = b;
@@ -4407,7 +4407,7 @@ public final class NormalizedNodeMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -4647,7 +4647,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesOrBuilderList() {
if (attributesBuilder_ != null) {
return attributesBuilder_.getMessageOrBuilderList();
@@ -4673,12 +4673,12 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Attribute attributes = 3;
*/
- public java.util.List
+ public java.util.List
getAttributesBuilderList() {
return getAttributesFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Attribute.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.AttributeOrBuilder>
getAttributesFieldBuilder() {
if (attributesBuilder_ == null) {
attributesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -4887,7 +4887,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getChildOrBuilderList() {
if (childBuilder_ != null) {
return childBuilder_.getMessageOrBuilderList();
@@ -4913,12 +4913,12 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Node child = 4;
*/
- public java.util.List
+ public java.util.List
getChildBuilderList() {
return getChildFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getChildFieldBuilder() {
if (childBuilder_ == null) {
childBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -4961,7 +4961,7 @@ public final class NormalizedNodeMessages {
getValueBytes() {
java.lang.Object ref = value_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
value_ = b;
@@ -5035,7 +5035,7 @@ public final class NormalizedNodeMessages {
getValueTypeBytes() {
java.lang.Object ref = valueType_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
valueType_ = b;
@@ -5277,7 +5277,7 @@ public final class NormalizedNodeMessages {
* optional .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierValue = 8;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierValueFieldBuilder() {
if (instanceIdentifierValueBuilder_ == null) {
instanceIdentifierValueBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -5459,7 +5459,7 @@ public final class NormalizedNodeMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -5475,7 +5475,7 @@ public final class NormalizedNodeMessages {
getParentPathBytes() {
java.lang.Object ref = parentPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
parentPath_ = b;
@@ -5751,12 +5751,12 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
if (!hasParentPath()) {
-
+
return false;
}
if (hasNormalizedNode()) {
if (!getNormalizedNode().isInitialized()) {
-
+
return false;
}
}
@@ -5811,7 +5811,7 @@ public final class NormalizedNodeMessages {
getParentPathBytes() {
java.lang.Object ref = parentPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
parentPath_ = b;
@@ -5960,7 +5960,7 @@ public final class NormalizedNodeMessages {
* optional .org.opendaylight.controller.mdsal.Node normalizedNode = 2;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getNormalizedNodeFieldBuilder() {
if (normalizedNodeBuilder_ == null) {
normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6431,16 +6431,16 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
if (!hasInstanceIdentifierPath()) {
-
+
return false;
}
if (!getInstanceIdentifierPath().isInitialized()) {
-
+
return false;
}
if (hasNormalizedNode()) {
if (!getNormalizedNode().isInitialized()) {
-
+
return false;
}
}
@@ -6570,7 +6570,7 @@ public final class NormalizedNodeMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPath = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierPathFieldBuilder() {
if (instanceIdentifierPathBuilder_ == null) {
instanceIdentifierPathBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6687,7 +6687,7 @@ public final class NormalizedNodeMessages {
* optional .org.opendaylight.controller.mdsal.Node normalizedNode = 2;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getNormalizedNodeFieldBuilder() {
if (normalizedNodeBuilder_ == null) {
normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6718,7 +6718,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
*/
- java.util.List
+ java.util.List
getMapEntriesList();
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
@@ -6731,7 +6731,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
getMapEntriesOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
@@ -6852,7 +6852,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
getMapEntriesOrBuilderList() {
return mapEntries_;
}
@@ -7105,7 +7105,7 @@ public final class NormalizedNodeMessages {
mapEntriesBuilder_ = null;
mapEntries_ = other.mapEntries_;
bitField0_ = (bitField0_ & ~0x00000001);
- mapEntriesBuilder_ =
+ mapEntriesBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getMapEntriesFieldBuilder() : null;
} else {
@@ -7120,7 +7120,7 @@ public final class NormalizedNodeMessages {
public final boolean isInitialized() {
for (int i = 0; i < getMapEntriesCount(); i++) {
if (!getMapEntries(i).isInitialized()) {
-
+
return false;
}
}
@@ -7341,7 +7341,7 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
getMapEntriesOrBuilderList() {
if (mapEntriesBuilder_ != null) {
return mapEntriesBuilder_.getMessageOrBuilderList();
@@ -7367,12 +7367,12 @@ public final class NormalizedNodeMessages {
/**
* repeated .org.opendaylight.controller.mdsal.NodeMapEntry mapEntries = 1;
*/
- public java.util.List
+ public java.util.List
getMapEntriesBuilderList() {
return getMapEntriesFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntry.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapEntryOrBuilder>
getMapEntriesFieldBuilder() {
if (mapEntriesBuilder_ == null) {
mapEntriesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java
index 67ab472d0c..29e54571d3 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/common/SimpleNormalizedNodeMessage.java
@@ -159,7 +159,7 @@ public final class SimpleNormalizedNodeMessage {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -175,7 +175,7 @@ public final class SimpleNormalizedNodeMessage {
getNodeIdentifierBytes() {
java.lang.Object ref = nodeIdentifier_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
nodeIdentifier_ = b;
@@ -202,7 +202,7 @@ public final class SimpleNormalizedNodeMessage {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -218,7 +218,7 @@ public final class SimpleNormalizedNodeMessage {
getXmlStringBytes() {
java.lang.Object ref = xmlString_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
xmlString_ = b;
@@ -463,11 +463,11 @@ public final class SimpleNormalizedNodeMessage {
public final boolean isInitialized() {
if (!hasNodeIdentifier()) {
-
+
return false;
}
if (!hasXmlString()) {
-
+
return false;
}
return true;
@@ -521,7 +521,7 @@ public final class SimpleNormalizedNodeMessage {
getNodeIdentifierBytes() {
java.lang.Object ref = nodeIdentifier_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
nodeIdentifier_ = b;
@@ -595,7 +595,7 @@ public final class SimpleNormalizedNodeMessage {
getXmlStringBytes() {
java.lang.Object ref = xmlString_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
xmlString_ = b;
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java
index 384b389f92..2018834768 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/datachange/notification/DataChangeListenerMessages.java
@@ -85,7 +85,7 @@ public final class DataChangeListenerMessages {
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
*/
- java.util.List
+ java.util.List
getRemovedPathsList();
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
@@ -98,7 +98,7 @@ public final class DataChangeListenerMessages {
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getRemovedPathsOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
@@ -395,7 +395,7 @@ public final class DataChangeListenerMessages {
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getRemovedPathsOrBuilderList() {
return removedPaths_;
}
@@ -810,7 +810,7 @@ public final class DataChangeListenerMessages {
removedPathsBuilder_ = null;
removedPaths_ = other.removedPaths_;
bitField0_ = (bitField0_ & ~0x00000020);
- removedPathsBuilder_ =
+ removedPathsBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getRemovedPathsFieldBuilder() : null;
} else {
@@ -825,37 +825,37 @@ public final class DataChangeListenerMessages {
public final boolean isInitialized() {
if (hasOriginalSubTree()) {
if (!getOriginalSubTree().isInitialized()) {
-
+
return false;
}
}
if (hasUpdatedSubTree()) {
if (!getUpdatedSubTree().isInitialized()) {
-
+
return false;
}
}
if (hasOriginalData()) {
if (!getOriginalData().isInitialized()) {
-
+
return false;
}
}
if (hasUpdatedData()) {
if (!getUpdatedData().isInitialized()) {
-
+
return false;
}
}
if (hasCreatedData()) {
if (!getCreatedData().isInitialized()) {
-
+
return false;
}
}
for (int i = 0; i < getRemovedPathsCount(); i++) {
if (!getRemovedPaths(i).isInitialized()) {
-
+
return false;
}
}
@@ -985,7 +985,7 @@ public final class DataChangeListenerMessages {
* optional .org.opendaylight.controller.mdsal.Node originalSubTree = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getOriginalSubTreeFieldBuilder() {
if (originalSubTreeBuilder_ == null) {
originalSubTreeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1102,7 +1102,7 @@ public final class DataChangeListenerMessages {
* optional .org.opendaylight.controller.mdsal.Node updatedSubTree = 2;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getUpdatedSubTreeFieldBuilder() {
if (updatedSubTreeBuilder_ == null) {
updatedSubTreeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1219,7 +1219,7 @@ public final class DataChangeListenerMessages {
* optional .org.opendaylight.controller.mdsal.NodeMap originalData = 3;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
getOriginalDataFieldBuilder() {
if (originalDataBuilder_ == null) {
originalDataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1336,7 +1336,7 @@ public final class DataChangeListenerMessages {
* optional .org.opendaylight.controller.mdsal.NodeMap updatedData = 4;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
getUpdatedDataFieldBuilder() {
if (updatedDataBuilder_ == null) {
updatedDataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1453,7 +1453,7 @@ public final class DataChangeListenerMessages {
* optional .org.opendaylight.controller.mdsal.NodeMap createdData = 5;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMap.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeMapOrBuilder>
getCreatedDataFieldBuilder() {
if (createdDataBuilder_ == null) {
createdDataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1661,7 +1661,7 @@ public final class DataChangeListenerMessages {
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getRemovedPathsOrBuilderList() {
if (removedPathsBuilder_ != null) {
return removedPathsBuilder_.getMessageOrBuilderList();
@@ -1687,12 +1687,12 @@ public final class DataChangeListenerMessages {
/**
* repeated .org.opendaylight.controller.mdsal.InstanceIdentifier removedPaths = 6;
*/
- public java.util.List
+ public java.util.List
getRemovedPathsBuilderList() {
return getRemovedPathsFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getRemovedPathsFieldBuilder() {
if (removedPathsBuilder_ == null) {
removedPathsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java
index 6c1e2722f6..eaa90012db 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/persistent/PersistentMessages.java
@@ -193,7 +193,7 @@ public final class PersistentMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -209,7 +209,7 @@ public final class PersistentMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -541,20 +541,20 @@ public final class PersistentMessages {
public final boolean isInitialized() {
if (!hasType()) {
-
+
return false;
}
if (!hasPath()) {
-
+
return false;
}
if (!getPath().isInitialized()) {
-
+
return false;
}
if (hasData()) {
if (!getData().isInitialized()) {
-
+
return false;
}
}
@@ -609,7 +609,7 @@ public final class PersistentMessages {
getTypeBytes() {
java.lang.Object ref = type_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
type_ = b;
@@ -758,7 +758,7 @@ public final class PersistentMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier path = 2;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getPathFieldBuilder() {
if (pathBuilder_ == null) {
pathBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -875,7 +875,7 @@ public final class PersistentMessages {
* optional .org.opendaylight.controller.mdsal.Node data = 3;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getDataFieldBuilder() {
if (dataBuilder_ == null) {
dataBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -906,7 +906,7 @@ public final class PersistentMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
*/
- java.util.List
+ java.util.List
getModificationList();
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
@@ -919,7 +919,7 @@ public final class PersistentMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
*/
- java.util.List extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
+ java.util.List extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
getModificationOrBuilderList();
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
@@ -1040,7 +1040,7 @@ public final class PersistentMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
getModificationOrBuilderList() {
return modification_;
}
@@ -1293,7 +1293,7 @@ public final class PersistentMessages {
modificationBuilder_ = null;
modification_ = other.modification_;
bitField0_ = (bitField0_ & ~0x00000001);
- modificationBuilder_ =
+ modificationBuilder_ =
com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getModificationFieldBuilder() : null;
} else {
@@ -1308,7 +1308,7 @@ public final class PersistentMessages {
public final boolean isInitialized() {
for (int i = 0; i < getModificationCount(); i++) {
if (!getModification(i).isInitialized()) {
-
+
return false;
}
}
@@ -1529,7 +1529,7 @@ public final class PersistentMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
*/
- public java.util.List extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
+ public java.util.List extends org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
getModificationOrBuilderList() {
if (modificationBuilder_ != null) {
return modificationBuilder_.getMessageOrBuilderList();
@@ -1555,12 +1555,12 @@ public final class PersistentMessages {
/**
* repeated .org.opendaylight.controller.mdsal.Modification modification = 1;
*/
- public java.util.List
+ public java.util.List
getModificationBuilderList() {
return getModificationFieldBuilder().getBuilderList();
}
private com.google.protobuf.RepeatedFieldBuilder<
- org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification.Builder, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
+ org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.Modification.Builder, org.opendaylight.controller.protobuff.messages.persistent.PersistentMessages.ModificationOrBuilder>
getModificationFieldBuilder() {
if (modificationBuilder_ == null) {
modificationBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
@@ -1605,15 +1605,16 @@ public final class PersistentMessages {
static {
java.lang.String[] descriptorData = {
"\n\020Persistent.proto\022!org.opendaylight.con" +
- "troller.mdsal\032\014Common.proto\"\230\001\n\014Modifica" +
- "tion\022\014\n\004type\030\001 \002(\t\022C\n\004path\030\002 \002(\01325.org.o" +
- "pendaylight.controller.mdsal.InstanceIde" +
- "ntifier\0225\n\004data\030\003 \001(\0132\'.org.opendaylight" +
- ".controller.mdsal.Node\"^\n\025CompositeModif" +
- "ication\022E\n\014modification\030\001 \003(\0132/.org.open" +
- "daylight.controller.mdsal.ModificationBO" +
- "\n9org.opendaylight.controller.protobuff." +
- "messages.persistentB\022PersistentMessages"
+ "troller.mdsal\032\014Common.proto\032\033AppendEntri" +
+ "esMessages.proto\"\230\001\n\014Modification\022\014\n\004typ" +
+ "e\030\001 \002(\t\022C\n\004path\030\002 \002(\01325.org.opendaylight" +
+ ".controller.mdsal.InstanceIdentifier\0225\n\004" +
+ "data\030\003 \001(\0132\'.org.opendaylight.controller" +
+ ".mdsal.Node\"^\n\025CompositeModification\022E\n\014" +
+ "modification\030\001 \003(\0132/.org.opendaylight.co" +
+ "ntroller.mdsal.ModificationBO\n9org.opend" +
+ "aylight.controller.protobuff.messages.pe",
+ "rsistentB\022PersistentMessages"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -1639,6 +1640,7 @@ public final class PersistentMessages {
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.getDescriptor(),
+ org.opendaylight.controller.cluster.raft.protobuff.messages.AppendEntriesMessages.getDescriptor(),
}, assigner);
}
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java
index 77cbd4da46..e06dd0d429 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/registration/ListenerRegistrationMessages.java
@@ -837,7 +837,7 @@ public final class ListenerRegistrationMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -853,7 +853,7 @@ public final class ListenerRegistrationMessages {
getDataChangeListenerActorPathBytes() {
java.lang.Object ref = dataChangeListenerActorPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
dataChangeListenerActorPath_ = b;
@@ -1146,19 +1146,19 @@ public final class ListenerRegistrationMessages {
public final boolean isInitialized() {
if (!hasInstanceIdentifierPath()) {
-
+
return false;
}
if (!hasDataChangeListenerActorPath()) {
-
+
return false;
}
if (!hasDataChangeScope()) {
-
+
return false;
}
if (!getInstanceIdentifierPath().isInitialized()) {
-
+
return false;
}
return true;
@@ -1287,7 +1287,7 @@ public final class ListenerRegistrationMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPath = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierPathFieldBuilder() {
if (instanceIdentifierPathBuilder_ == null) {
instanceIdentifierPathBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -1329,7 +1329,7 @@ public final class ListenerRegistrationMessages {
getDataChangeListenerActorPathBytes() {
java.lang.Object ref = dataChangeListenerActorPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
dataChangeListenerActorPath_ = b;
@@ -1556,7 +1556,7 @@ public final class ListenerRegistrationMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1572,7 +1572,7 @@ public final class ListenerRegistrationMessages {
getListenerRegistrationPathBytes() {
java.lang.Object ref = listenerRegistrationPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
listenerRegistrationPath_ = b;
@@ -1801,7 +1801,7 @@ public final class ListenerRegistrationMessages {
public final boolean isInitialized() {
if (!hasListenerRegistrationPath()) {
-
+
return false;
}
return true;
@@ -1855,7 +1855,7 @@ public final class ListenerRegistrationMessages {
getListenerRegistrationPathBytes() {
java.lang.Object ref = listenerRegistrationPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
listenerRegistrationPath_ = b;
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java
index 2324dfc2a2..7c2a47e1b0 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/shard/ShardManagerMessages.java
@@ -139,7 +139,7 @@ public final class ShardManagerMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -155,7 +155,7 @@ public final class ShardManagerMessages {
getShardNameBytes() {
java.lang.Object ref = shardName_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
shardName_ = b;
@@ -377,7 +377,7 @@ public final class ShardManagerMessages {
public final boolean isInitialized() {
if (!hasShardName()) {
-
+
return false;
}
return true;
@@ -431,7 +431,7 @@ public final class ShardManagerMessages {
getShardNameBytes() {
java.lang.Object ref = shardName_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
shardName_ = b;
@@ -618,7 +618,7 @@ public final class ShardManagerMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -634,7 +634,7 @@ public final class ShardManagerMessages {
getPrimaryPathBytes() {
java.lang.Object ref = primaryPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
primaryPath_ = b;
@@ -856,7 +856,7 @@ public final class ShardManagerMessages {
public final boolean isInitialized() {
if (!hasPrimaryPath()) {
-
+
return false;
}
return true;
@@ -910,7 +910,7 @@ public final class ShardManagerMessages {
getPrimaryPathBytes() {
java.lang.Object ref = primaryPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
primaryPath_ = b;
@@ -1097,7 +1097,7 @@ public final class ShardManagerMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1113,7 +1113,7 @@ public final class ShardManagerMessages {
getShardNameBytes() {
java.lang.Object ref = shardName_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
shardName_ = b;
@@ -1335,7 +1335,7 @@ public final class ShardManagerMessages {
public final boolean isInitialized() {
if (!hasShardName()) {
-
+
return false;
}
return true;
@@ -1389,7 +1389,7 @@ public final class ShardManagerMessages {
getShardNameBytes() {
java.lang.Object ref = shardName_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
shardName_ = b;
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java
index 63dd5e7081..3f354ba40e 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionChainMessages.java
@@ -1066,7 +1066,7 @@ public final class ShardTransactionChainMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1082,7 +1082,7 @@ public final class ShardTransactionChainMessages {
getTransactionChainPathBytes() {
java.lang.Object ref = transactionChainPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionChainPath_ = b;
@@ -1304,7 +1304,7 @@ public final class ShardTransactionChainMessages {
public final boolean isInitialized() {
if (!hasTransactionChainPath()) {
-
+
return false;
}
return true;
@@ -1358,7 +1358,7 @@ public final class ShardTransactionChainMessages {
getTransactionChainPathBytes() {
java.lang.Object ref = transactionChainPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionChainPath_ = b;
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java
index 7ce3b586b4..ee2c70423e 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java
@@ -757,7 +757,7 @@ public final class ShardTransactionMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -773,7 +773,7 @@ public final class ShardTransactionMessages {
getTransactionIdBytes() {
java.lang.Object ref = transactionId_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionId_ = b;
@@ -995,7 +995,7 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasTransactionId()) {
-
+
return false;
}
return true;
@@ -1049,7 +1049,7 @@ public final class ShardTransactionMessages {
getTransactionIdBytes() {
java.lang.Object ref = transactionId_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionId_ = b;
@@ -1256,7 +1256,7 @@ public final class ShardTransactionMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1272,7 +1272,7 @@ public final class ShardTransactionMessages {
getTransactionActorPathBytes() {
java.lang.Object ref = transactionActorPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionActorPath_ = b;
@@ -1299,7 +1299,7 @@ public final class ShardTransactionMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -1315,7 +1315,7 @@ public final class ShardTransactionMessages {
getTransactionIdBytes() {
java.lang.Object ref = transactionId_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionId_ = b;
@@ -1560,11 +1560,11 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasTransactionActorPath()) {
-
+
return false;
}
if (!hasTransactionId()) {
-
+
return false;
}
return true;
@@ -1618,7 +1618,7 @@ public final class ShardTransactionMessages {
getTransactionActorPathBytes() {
java.lang.Object ref = transactionActorPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionActorPath_ = b;
@@ -1692,7 +1692,7 @@ public final class ShardTransactionMessages {
getTransactionIdBytes() {
java.lang.Object ref = transactionId_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
transactionId_ = b;
@@ -2188,7 +2188,7 @@ public final class ShardTransactionMessages {
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
- com.google.protobuf.ByteString bs =
+ com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
@@ -2204,7 +2204,7 @@ public final class ShardTransactionMessages {
getActorPathBytes() {
java.lang.Object ref = actorPath_;
if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
actorPath_ = b;
@@ -2426,7 +2426,7 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasActorPath()) {
-
+
return false;
}
return true;
@@ -2480,7 +2480,7 @@ public final class ShardTransactionMessages {
getActorPathBytes() {
java.lang.Object ref = actorPath_;
if (ref instanceof String) {
- com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
actorPath_ = b;
@@ -2902,11 +2902,11 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasInstanceIdentifierPathArguments()) {
-
+
return false;
}
if (!getInstanceIdentifierPathArguments().isInitialized()) {
-
+
return false;
}
return true;
@@ -3035,7 +3035,7 @@ public final class ShardTransactionMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierPathArgumentsFieldBuilder() {
if (instanceIdentifierPathArgumentsBuilder_ == null) {
instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -3734,11 +3734,11 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasInstanceIdentifierPathArguments()) {
-
+
return false;
}
if (!getInstanceIdentifierPathArguments().isInitialized()) {
-
+
return false;
}
return true;
@@ -3867,7 +3867,7 @@ public final class ShardTransactionMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierPathArgumentsFieldBuilder() {
if (instanceIdentifierPathArgumentsBuilder_ == null) {
instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -4256,7 +4256,7 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (hasNormalizedNode()) {
if (!getNormalizedNode().isInitialized()) {
-
+
return false;
}
}
@@ -4386,7 +4386,7 @@ public final class ShardTransactionMessages {
* optional .org.opendaylight.controller.mdsal.Node normalizedNode = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getNormalizedNodeFieldBuilder() {
if (normalizedNodeBuilder_ == null) {
normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -4859,19 +4859,19 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasInstanceIdentifierPathArguments()) {
-
+
return false;
}
if (!hasNormalizedNode()) {
-
+
return false;
}
if (!getInstanceIdentifierPathArguments().isInitialized()) {
-
+
return false;
}
if (!getNormalizedNode().isInitialized()) {
-
+
return false;
}
return true;
@@ -5000,7 +5000,7 @@ public final class ShardTransactionMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierPathArgumentsFieldBuilder() {
if (instanceIdentifierPathArgumentsBuilder_ == null) {
instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -5117,7 +5117,7 @@ public final class ShardTransactionMessages {
* required .org.opendaylight.controller.mdsal.Node normalizedNode = 2;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getNormalizedNodeFieldBuilder() {
if (normalizedNodeBuilder_ == null) {
normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -5899,19 +5899,19 @@ public final class ShardTransactionMessages {
public final boolean isInitialized() {
if (!hasInstanceIdentifierPathArguments()) {
-
+
return false;
}
if (!hasNormalizedNode()) {
-
+
return false;
}
if (!getInstanceIdentifierPathArguments().isInitialized()) {
-
+
return false;
}
if (!getNormalizedNode().isInitialized()) {
-
+
return false;
}
return true;
@@ -6040,7 +6040,7 @@ public final class ShardTransactionMessages {
* required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>
getInstanceIdentifierPathArgumentsFieldBuilder() {
if (instanceIdentifierPathArgumentsBuilder_ == null) {
instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
@@ -6157,7 +6157,7 @@ public final class ShardTransactionMessages {
* required .org.opendaylight.controller.mdsal.Node normalizedNode = 2;
*/
private com.google.protobuf.SingleFieldBuilder<
- org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
+ org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.NodeOrBuilder>
getNormalizedNodeFieldBuilder() {
if (normalizedNodeBuilder_ == null) {
normalizedNodeBuilder_ = new com.google.protobuf.SingleFieldBuilder<
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/CompositeModificationPayload.proto b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/CompositeModificationPayload.proto
new file mode 100644
index 0000000000..b571cd25c5
--- /dev/null
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/CompositeModificationPayload.proto
@@ -0,0 +1,11 @@
+package org.opendaylight.controller.mdsal;
+
+import "AppendEntriesMessages.proto";
+import "Common.proto";
+import "Persistent.proto";
+
+extend org.opendaylight.controller.cluster.raft.AppendEntries.ReplicatedLogEntry.Payload {
+ optional CompositeModification modification=2;
+}
+
+
diff --git a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Persistent.proto b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Persistent.proto
index b3f28197ed..8e834494cb 100644
--- a/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Persistent.proto
+++ b/opendaylight/md-sal/sal-protocolbuffer-encoding/src/main/resources/Persistent.proto
@@ -1,6 +1,7 @@
package org.opendaylight.controller.mdsal;
import "Common.proto";
+import "AppendEntriesMessages.proto";
option java_package = "org.opendaylight.controller.protobuff.messages.persistent";
option java_outer_classname = "PersistentMessages";
@@ -16,3 +17,4 @@ message Modification {
message CompositeModification {
repeated Modification modification=1;
}
+
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/pom.xml b/opendaylight/md-sal/sal-remoterpc-connector/pom.xml
index 6ee301d827..ce3bfe9a4c 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/pom.xml
+++ b/opendaylight/md-sal/sal-remoterpc-connector/pom.xml
@@ -55,22 +55,37 @@
org.opendaylight.controllernetconf-util
-
+
+ org.opendaylight.controller
+ sal-core-spi
+
+
+ org.opendaylight.controller
+ sal-common-impl
+ org.opendaylight.yangtoolsyang-data-api
+
+
+ org.opendaylight.yangtools
+ yang-model-api
+
+ org.opendaylight.yangtoolsyang-data-impl
+
org.opendaylight.yangtoolsyang-common
+
@@ -107,6 +122,17 @@
${slf4j.version}test
+
+ org.opendaylight.yangtools
+ yang-parser-impl
+ test
+
+
+ com.google.collections
+ google-collections
+ 1.0
+ test
+
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java
index 8315bbeeb3..9824889b80 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java
@@ -2,10 +2,8 @@ package org.opendaylight.controller.config.yang.config.remote_rpc_connector;
import org.opendaylight.controller.remote.rpc.RemoteRpcProviderFactory;
import org.opendaylight.controller.sal.core.api.Broker;
-import org.osgi.framework.BundleContext;
public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModule {
- private BundleContext bundleContext;
public RemoteRPCBrokerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
@@ -22,10 +20,6 @@ public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.ya
@Override
public java.lang.AutoCloseable createInstance() {
Broker broker = getDomBrokerDependency();
- return RemoteRpcProviderFactory.createInstance(broker, bundleContext);
- }
-
- public void setBundleContext(final BundleContext bundleContext) {
- this.bundleContext = bundleContext;
+ return RemoteRpcProviderFactory.createInstance(broker);
}
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java
index e1ba46ae15..330845b14f 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java
@@ -9,27 +9,7 @@
*/
package org.opendaylight.controller.config.yang.config.remote_rpc_connector;
-import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
-import org.opendaylight.controller.config.spi.Module;
-import org.osgi.framework.BundleContext;
public class RemoteRPCBrokerModuleFactory extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModuleFactory {
- @Override
- public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
- RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName,dependencyResolver,bundleContext);
- module.setBundleContext(bundleContext);
- return module;
- }
-
- @Override
- public Module createModule(String instanceName, DependencyResolver dependencyResolver,
- DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception {
- RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName, dependencyResolver,
- old, bundleContext);
- module.setBundleContext(bundleContext);
- return module;
- }
-
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java
new file mode 100644
index 0000000000..1f1a0f5cc6
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorConstants.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 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.controller.remote.rpc;
+
+
+public class ActorConstants {
+ public static final String RPC_BROKER = "rpc-broker";
+ public static final String RPC_REGISTRY = "rpc-registry";
+ public static final String RPC_MANAGER = "rpc";
+
+ public static final String RPC_BROKER_PATH= "/user/rpc/rpc-broker";
+ public static final String RPC_REGISTRY_PATH = "/user/rpc/rpc-registry";
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcImplementation.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcImplementation.java
index 43aa5b7e85..d384144f4f 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcImplementation.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcImplementation.java
@@ -7,21 +7,19 @@ import org.opendaylight.controller.remote.rpc.messages.ErrorResponse;
import org.opendaylight.controller.remote.rpc.messages.InvokeRoutedRpc;
import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
+import org.opendaylight.controller.remote.rpc.utils.XmlUtils;
import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Set;
@@ -37,7 +35,7 @@ public class RemoteRpcImplementation implements RpcImplementation,
}
@Override
- public ListenableFuture> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
+ public ListenableFuture> invokeRpc(QName rpc, YangInstanceIdentifier identifier, CompositeNode input) {
InvokeRoutedRpc rpcMsg = new InvokeRoutedRpc(rpc, identifier, input);
return executeMsg(rpcMsg);
@@ -56,22 +54,33 @@ public class RemoteRpcImplementation implements RpcImplementation,
}
private ListenableFuture> executeMsg(Object rpcMsg) {
- CompositeNode result = null;
- Collection errors = errors = new ArrayList<>();
+ ListenableFuture> listenableFuture = null;
+
try {
Object response = ActorUtil.executeLocalOperation(rpcBroker, rpcMsg, ActorUtil.ASK_DURATION, ActorUtil.AWAIT_DURATION);
if(response instanceof RpcResponse) {
+
RpcResponse rpcResponse = (RpcResponse) response;
- result = XmlUtils.xmlToCompositeNode(rpcResponse.getResultCompositeNode());
+ CompositeNode result = XmlUtils.xmlToCompositeNode(rpcResponse.getResultCompositeNode());
+ listenableFuture = Futures.immediateFuture(RpcResultBuilder.success(result).build());
+
} else if(response instanceof ErrorResponse) {
+
ErrorResponse errorResponse = (ErrorResponse) response;
Exception e = errorResponse.getException();
- errors.add(RpcErrors.getRpcError(null, null, null, null, e.getMessage(), null, e.getCause()));
+ final RpcResultBuilder failed = RpcResultBuilder.failed();
+ failed.withError(null, null, e.getMessage(), null, null, e.getCause());
+ listenableFuture = Futures.immediateFuture(failed.build());
+
}
} catch (Exception e) {
LOG.error("Error occurred while invoking RPC actor {}", e.toString());
- errors.add(RpcErrors.getRpcError(null, null, null, null, e.getMessage(), null, e.getCause()));
+
+ final RpcResultBuilder failed = RpcResultBuilder.failed();
+ failed.withError(null, null, e.getMessage(), null, null, e.getCause());
+ listenableFuture = Futures.immediateFuture(failed.build());
}
- return Futures.immediateFuture(Rpcs.getRpcResult(true, result, errors));
+
+ return listenableFuture;
}
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProvider.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProvider.java
index 1bb7ea4514..ac50b8fe5b 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProvider.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProvider.java
@@ -11,37 +11,35 @@ package org.opendaylight.controller.remote.rpc;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
+import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
import org.opendaylight.controller.remote.rpc.registry.ClusterWrapperImpl;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
-import java.util.Set;
/**
* This is the base class which initialize all the actors, listeners and
* default RPc implementation so remote invocation of rpcs.
*/
-public class RemoteRpcProvider implements AutoCloseable, Provider{
+public class RemoteRpcProvider implements AutoCloseable, Provider, SchemaContextListener {
private static final Logger LOG = LoggerFactory.getLogger(RemoteRpcProvider.class);
private final ActorSystem actorSystem;
- private ActorRef rpcBroker;
- private ActorRef rpcRegistry;
private final RpcProvisionRegistry rpcProvisionRegistry;
private Broker.ProviderSession brokerSession;
- private RpcListener rpcListener;
- private RoutedRpcListener routeChangeListener;
- private RemoteRpcImplementation rpcImplementation;
+ private SchemaContext schemaContext;
+ private ActorRef rpcManager;
+
+
public RemoteRpcProvider(ActorSystem actorSystem, RpcProvisionRegistry rpcProvisionRegistry) {
this.actorSystem = actorSystem;
this.rpcProvisionRegistry = rpcProvisionRegistry;
@@ -50,8 +48,6 @@ public class RemoteRpcProvider implements AutoCloseable, Provider{
@Override
public void close() throws Exception {
this.actorSystem.shutdown();
- unregisterSupportedRpcs();
- unregisterSupportedRoutedRpcs();
}
@Override
@@ -66,64 +62,22 @@ public class RemoteRpcProvider implements AutoCloseable, Provider{
}
private void start() {
- LOG.debug("Starting all rpc listeners.");
+ LOG.info("Starting all rpc listeners and actors.");
// Create actor to handle and sync routing table in cluster
ClusterWrapper clusterWrapper = new ClusterWrapperImpl(actorSystem);
- rpcRegistry = actorSystem.actorOf(RpcRegistry.props(clusterWrapper), "rpc-registry");
-
- // Create actor to invoke and execute rpc
SchemaService schemaService = brokerSession.getService(SchemaService.class);
- SchemaContext schemaContext = schemaService.getGlobalContext();
- rpcBroker = actorSystem.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), "rpc-broker");
- String rpcBrokerPath = clusterWrapper.getAddress().toString() + "/user/rpc-broker";
- rpcListener = new RpcListener(rpcRegistry, rpcBrokerPath);
- routeChangeListener = new RoutedRpcListener(rpcRegistry, rpcBrokerPath);
- rpcImplementation = new RemoteRpcImplementation(rpcBroker, schemaContext);
- brokerSession.addRpcRegistrationListener(rpcListener);
- rpcProvisionRegistry.registerRouteChangeListener(routeChangeListener);
- rpcProvisionRegistry.setRoutedRpcDefaultDelegate(rpcImplementation);
- announceSupportedRpcs();
- announceSupportedRoutedRpcs();
+ schemaContext = schemaService.getGlobalContext();
- }
+ rpcManager = actorSystem.actorOf(RpcManager.props(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry), ActorConstants.RPC_MANAGER);
- /**
- * Add all the locally registered RPCs in the clustered routing table
- */
- private void announceSupportedRpcs(){
- LOG.debug("Adding all supported rpcs to routing table");
- Set currentlySupported = brokerSession.getSupportedRpcs();
- for (QName rpc : currentlySupported) {
- rpcListener.onRpcImplementationAdded(rpc);
- }
+ LOG.debug("Rpc actors are created.");
}
- /**
- * Add all the locally registered Routed RPCs in the clustered routing table
- */
- private void announceSupportedRoutedRpcs(){
-
- //TODO: announce all routed RPCs as well
- }
-
- /**
- * Un-Register all the supported RPCs from clustered routing table
- */
- private void unregisterSupportedRpcs(){
- LOG.debug("removing all supported rpcs to routing table");
- Set currentlySupported = brokerSession.getSupportedRpcs();
- for (QName rpc : currentlySupported) {
- rpcListener.onRpcImplementationRemoved(rpc);
- }
- }
-
- /**
- * Un-Register all the locally supported Routed RPCs from clustered routing table
- */
- private void unregisterSupportedRoutedRpcs(){
-
- //TODO: remove all routed RPCs as well
+ @Override
+ public void onGlobalContextUpdated(SchemaContext schemaContext) {
+ this.schemaContext = schemaContext;
+ rpcManager.tell(new UpdateSchemaContext(schemaContext), null);
}
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java
index 61dc8183df..4c40ca1777 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RemoteRpcProviderFactory.java
@@ -11,13 +11,12 @@ package org.opendaylight.controller.remote.rpc;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.osgi.framework.BundleContext;
public class RemoteRpcProviderFactory {
- public static RemoteRpcProvider createInstance(final Broker broker, final BundleContext bundleContext){
+ public static RemoteRpcProvider createInstance(final Broker broker){
RemoteRpcProvider rpcProvider =
new RemoteRpcProvider(ActorSystemFactory.getInstance(), (RpcProvisionRegistry) broker);
- broker.registerProvider(rpcProvider, bundleContext);
+ broker.registerProvider(rpcProvider);
return rpcProvider;
}
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RouteIdentifierImpl.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RouteIdentifierImpl.java
index ea72238fbc..85d21381b6 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RouteIdentifierImpl.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RouteIdentifierImpl.java
@@ -7,20 +7,23 @@
*/
package org.opendaylight.controller.remote.rpc;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
import java.io.Serializable;
-public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable {
+public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier,Serializable {
private static final long serialVersionUID = 1L;
- private QName context;
- private QName type;
- private InstanceIdentifier route;
+ private final QName context;
+ private final QName type;
+ private final YangInstanceIdentifier route;
- public RouteIdentifierImpl(QName context, QName type, InstanceIdentifier route) {
+ public RouteIdentifierImpl(final QName context, final QName type, final YangInstanceIdentifier route) {
+ Preconditions.checkNotNull(type, "Rpc type should not be null");
this.context = context;
this.type = type;
this.route = route;
@@ -37,7 +40,7 @@ public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier{
+public class RoutedRpcListener implements RouteChangeListener{
private static final Logger LOG = LoggerFactory.getLogger(RoutedRpcListener.class);
private final ActorRef rpcRegistry;
private final String actorPath;
public RoutedRpcListener(ActorRef rpcRegistry, String actorPath) {
+ Preconditions.checkNotNull(rpcRegistry, "rpc registry actor should not be null");
+ Preconditions.checkNotNull(actorPath, "actor path of rpc broker on current node should not be null");
+
this.rpcRegistry = rpcRegistry;
this.actorPath = actorPath;
}
@Override
- public void onRouteChange(RouteChange routeChange) {
- Map> announcements = routeChange.getAnnouncements();
+ public void onRouteChange(RouteChange routeChange) {
+ Map> announcements = routeChange.getAnnouncements();
announce(getRouteIdentifiers(announcements));
- Map> removals = routeChange.getRemovals();
+ Map> removals = routeChange.getRemovals();
remove(getRouteIdentifiers(removals));
}
@@ -78,12 +83,12 @@ public class RoutedRpcListener implements RouteChangeListener> getRouteIdentifiers(Map> changes) {
+ private Set> getRouteIdentifiers(Map> changes) {
RouteIdentifierImpl routeId = null;
Set> routeIdSet = new HashSet<>();
for (RpcRoutingContext context : changes.keySet()){
- for (InstanceIdentifier instanceId : changes.get(context)){
+ for (YangInstanceIdentifier instanceId : changes.get(context)){
routeId = new RouteIdentifierImpl(null, context.getRpc(), instanceId);
routeIdSet.add(routeId);
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcBroker.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcBroker.java
index 3354fc3da2..26e8e960e3 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcBroker.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcBroker.java
@@ -20,6 +20,8 @@ import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
import org.opendaylight.controller.remote.rpc.messages.InvokeRoutedRpc;
import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
+import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
+import org.opendaylight.controller.remote.rpc.utils.XmlUtils;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -38,7 +40,7 @@ public class RpcBroker extends AbstractUntypedActor {
private static final Logger LOG = LoggerFactory.getLogger(RpcBroker.class);
private final Broker.ProviderSession brokerSession;
private final ActorRef rpcRegistry;
- private final SchemaContext schemaContext;
+ private SchemaContext schemaContext;
private RpcBroker(Broker.ProviderSession brokerSession, ActorRef rpcRegistry, SchemaContext schemaContext){
this.brokerSession = brokerSession;
@@ -72,7 +74,7 @@ public class RpcBroker extends AbstractUntypedActor {
try {
RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, msg.getRpc(), msg.getIdentifier());
GetRoutedRpc routedRpcMsg = new GetRoutedRpc(routeId);
- GetRoutedRpcReply rpcReply = (GetRoutedRpcReply)ActorUtil.executeLocalOperation(rpcRegistry, routedRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
+ GetRoutedRpcReply rpcReply = (GetRoutedRpcReply) ActorUtil.executeLocalOperation(rpcRegistry, routedRpcMsg, ActorUtil.LOCAL_ASK_DURATION, ActorUtil.LOCAL_AWAIT_DURATION);
String remoteActorPath = rpcReply.getRoutePath();
if(remoteActorPath == null) {
@@ -105,11 +107,12 @@ public class RpcBroker extends AbstractUntypedActor {
String remoteActorPath = rpcReply.getRoutePath();
if(remoteActorPath == null) {
- LOG.debug("No remote actor found for rpc execution.");
+ LOG.debug("No remote actor found for rpc {{}}.", msg.getRpc());
getSender().tell(new ErrorResponse(
- new IllegalStateException("No remote actor found for rpc execution.")), self());
+ new IllegalStateException("No remote actor found for rpc execution of : " + msg.getRpc())), self());
} else {
+
ExecuteRpc executeMsg = new ExecuteRpc(XmlUtils.inputCompositeNodeToXml(msg.getInput(), schemaContext), msg.getRpc());
Object operationRes = ActorUtil.executeRemoteOperation(this.context().actorSelection(remoteActorPath),
executeMsg, ActorUtil.REMOTE_ASK_DURATION, ActorUtil.REMOTE_AWAIT_DURATION);
@@ -127,7 +130,6 @@ public class RpcBroker extends AbstractUntypedActor {
try {
Future> rpc = brokerSession.rpc(msg.getRpc(), XmlUtils.inputXmlToCompositeNode(msg.getRpc(), msg.getInputCompositeNode(), schemaContext));
RpcResult rpcResult = rpc != null ? rpc.get():null;
-
CompositeNode result = rpcResult != null ? rpcResult.getResult() : null;
getSender().tell(new RpcResponse(XmlUtils.outputCompositeNodeToXml(result, schemaContext)), self());
} catch (Exception e) {
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcListener.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcListener.java
index ae760fadc4..f614990669 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcListener.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcListener.java
@@ -12,6 +12,7 @@ package org.opendaylight.controller.remote.rpc;
import akka.actor.ActorRef;
import org.opendaylight.controller.remote.rpc.messages.AddRpc;
import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
+import org.opendaylight.controller.remote.rpc.utils.ActorUtil;
import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
import org.opendaylight.yangtools.yang.common.QName;
import org.slf4j.Logger;
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcManager.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcManager.java
new file mode 100644
index 0000000000..5c56455bd0
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/RpcManager.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 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.controller.remote.rpc;
+
+
+import akka.actor.ActorRef;
+import akka.actor.OneForOneStrategy;
+import akka.actor.Props;
+import akka.actor.SupervisorStrategy;
+import akka.japi.Creator;
+import akka.japi.Function;
+import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
+import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.duration.Duration;
+import java.util.Set;
+
+/**
+ * This class acts as a supervisor, creates all the actors, resumes them, if an exception is thrown.
+ *
+ * It also starts the rpc listeners
+ */
+
+public class RpcManager extends AbstractUntypedActor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RpcManager.class);
+
+ private SchemaContext schemaContext;
+ private final ClusterWrapper clusterWrapper;
+ private ActorRef rpcBroker;
+ private ActorRef rpcRegistry;
+ private final Broker.ProviderSession brokerSession;
+ private RpcListener rpcListener;
+ private RoutedRpcListener routeChangeListener;
+ private RemoteRpcImplementation rpcImplementation;
+ private final RpcProvisionRegistry rpcProvisionRegistry;
+
+ private RpcManager(ClusterWrapper clusterWrapper, SchemaContext schemaContext,
+ Broker.ProviderSession brokerSession, RpcProvisionRegistry rpcProvisionRegistry) {
+ this.clusterWrapper = clusterWrapper;
+ this.schemaContext = schemaContext;
+ this.brokerSession = brokerSession;
+ this.rpcProvisionRegistry = rpcProvisionRegistry;
+
+ createRpcActors();
+ startListeners();
+ }
+
+
+ public static Props props(final ClusterWrapper clusterWrapper, final SchemaContext schemaContext,
+ final Broker.ProviderSession brokerSession, final RpcProvisionRegistry rpcProvisionRegistry) {
+ return Props.create(new Creator() {
+ @Override
+ public RpcManager create() throws Exception {
+ return new RpcManager(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry);
+ }
+ });
+ }
+
+ private void createRpcActors() {
+ LOG.debug("Create rpc registry and broker actors");
+
+ rpcRegistry = getContext().actorOf(RpcRegistry.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
+ rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), ActorConstants.RPC_BROKER);
+ }
+
+ private void startListeners() {
+ LOG.debug("Registers rpc listeners");
+
+ String rpcBrokerPath = clusterWrapper.getAddress().toString() + ActorConstants.RPC_BROKER_PATH;
+ rpcListener = new RpcListener(rpcRegistry, rpcBrokerPath);
+ routeChangeListener = new RoutedRpcListener(rpcRegistry, rpcBrokerPath);
+ rpcImplementation = new RemoteRpcImplementation(rpcBroker, schemaContext);
+
+ brokerSession.addRpcRegistrationListener(rpcListener);
+ rpcProvisionRegistry.registerRouteChangeListener(routeChangeListener);
+ rpcProvisionRegistry.setRoutedRpcDefaultDelegate(rpcImplementation);
+ announceSupportedRpcs();
+ }
+
+ /**
+ * Add all the locally registered RPCs in the clustered routing table
+ */
+ private void announceSupportedRpcs(){
+ LOG.debug("Adding all supported rpcs to routing table");
+ Set currentlySupported = brokerSession.getSupportedRpcs();
+ for (QName rpc : currentlySupported) {
+ rpcListener.onRpcImplementationAdded(rpc);
+ }
+ }
+
+
+ @Override
+ protected void handleReceive(Object message) throws Exception {
+ if(message instanceof UpdateSchemaContext) {
+ updateSchemaContext((UpdateSchemaContext) message);
+ }
+
+ }
+
+ private void updateSchemaContext(UpdateSchemaContext message) {
+ this.schemaContext = message.getSchemaContext();
+ }
+
+ @Override
+ public SupervisorStrategy supervisorStrategy() {
+ return new OneForOneStrategy(10, Duration.create("1 minute"),
+ new Function() {
+ @Override
+ public SupervisorStrategy.Directive apply(Throwable t) {
+ return SupervisorStrategy.resume();
+ }
+ }
+ );
+ }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/XmlUtils.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/XmlUtils.java
deleted file mode 100644
index 5fb2bb8772..0000000000
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/XmlUtils.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2014 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.controller.remote.rpc;
-
-import com.google.common.base.Optional;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import javax.activation.UnsupportedDataTypeException;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.Set;
-
-public class XmlUtils {
-
- private static final Logger LOG = LoggerFactory.getLogger(XmlUtils.class);
-
- public static String inputCompositeNodeToXml(CompositeNode cNode, SchemaContext schemaContext){
- if (cNode == null) return new String();
-
- //Document domTree = NodeUtils.buildShadowDomTree(cNode);
- Document domTree = null;
- try {
- Set rpcs = schemaContext.getOperations();
- for(RpcDefinition rpc : rpcs) {
- if(rpc.getQName().equals(cNode.getNodeType())){
- domTree = XmlDocumentUtils.toDocument(cNode, rpc.getInput(), XmlDocumentUtils.defaultValueCodecProvider());
- break;
- }
- }
-
- } catch (UnsupportedDataTypeException e) {
- LOG.error("Error during translation of CompositeNode to Document", e);
- }
- return domTransformer(domTree);
- }
-
- public static String outputCompositeNodeToXml(CompositeNode cNode, SchemaContext schemaContext){
- if (cNode == null) return new String();
-
- //Document domTree = NodeUtils.buildShadowDomTree(cNode);
- Document domTree = null;
- try {
- Set rpcs = schemaContext.getOperations();
- for(RpcDefinition rpc : rpcs) {
- if(rpc.getQName().equals(cNode.getNodeType())){
- domTree = XmlDocumentUtils.toDocument(cNode, rpc.getInput(), XmlDocumentUtils.defaultValueCodecProvider());
- break;
- }
- }
-
- } catch (UnsupportedDataTypeException e) {
- LOG.error("Error during translation of CompositeNode to Document", e);
- }
- return domTransformer(domTree);
- }
-
- private static String domTransformer(Document domTree) {
- StringWriter writer = new StringWriter();
- try {
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer transformer = tf.newTransformer();
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- transformer.transform(new DOMSource(domTree), new StreamResult(writer));
- } catch (TransformerException e) {
-
- LOG.error("Error during translation of Document to OutputStream", e);
- }
- LOG.debug("compositeNodeToXml " + writer.toString());
-
- return writer.toString();
- }
-
- public static CompositeNode xmlToCompositeNode(String xml){
- if (xml==null || xml.length()==0) return null;
-
- Node> dataTree;
- try {
- dataTree = XmlTreeBuilder.buildDataTree(new ByteArrayInputStream(xml.getBytes()));
- } catch (XMLStreamException e) {
- LOG.error("Error during building data tree from XML", e);
- return null;
- }
- if (dataTree == null) {
- LOG.error("data tree is null");
- return null;
- }
- if (dataTree instanceof SimpleNode) {
- LOG.error("RPC XML was resolved as SimpleNode");
- return null;
- }
- return (CompositeNode) dataTree;
- }
-
- public static CompositeNode inputXmlToCompositeNode(QName rpc, String xml, SchemaContext schemaContext){
- if (xml==null || xml.length()==0) return null;
-
- Node> dataTree = null;
- try {
-
- Document doc = XmlUtil.readXmlToDocument(xml);
- LOG.debug("xmlToCompositeNode Document is " + xml );
- Set rpcs = schemaContext.getOperations();
- for(RpcDefinition rpcDef : rpcs) {
- if(rpcDef.getQName().equals(rpc)){
- dataTree = XmlDocumentUtils.toDomNode(doc.getDocumentElement(), Optional.of(rpcDef.getInput()), Optional.of(XmlDocumentUtils.defaultValueCodecProvider()));
- break;
- }
- }
- } catch (SAXException e) {
- LOG.error("Error during building data tree from XML", e);
- } catch (IOException e) {
- LOG.error("Error during building data tree from XML", e);
- }
-
- LOG.debug("xmlToCompositeNode " + dataTree.toString());
- return (CompositeNode) dataTree;
- }
-}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java
index 25773bb8a6..fd1af2b33c 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRoutedRpc.java
@@ -8,6 +8,7 @@
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import java.io.Serializable;
@@ -15,10 +16,13 @@ import java.util.Set;
public class AddRoutedRpc implements Serializable {
- Set> announcements;
- String actorPath;
+ private final Set> announcements;
+ private final String actorPath;
+
+ public AddRoutedRpc(final Set> announcements, final String actorPath) {
+ Preconditions.checkNotNull(announcements, "Route identifier should not be null");
+ Preconditions.checkNotNull(actorPath, "Actor path should not be null");
- public AddRoutedRpc(Set> announcements, String actorPath) {
this.announcements = announcements;
this.actorPath = actorPath;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java
index eac973137e..7eaa8f0618 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/AddRpc.java
@@ -8,16 +8,20 @@
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
import java.io.Serializable;
public class AddRpc implements Serializable {
- RouteIdentifierImpl routeId;
- String actorPath;
+ private final RouteIdentifierImpl routeId;
+ private final String actorPath;
+
+ public AddRpc(final RouteIdentifierImpl routeId, final String actorPath) {
+ Preconditions.checkNotNull(routeId, "Route identifier should not be null");
+ Preconditions.checkNotNull(actorPath, "Actor path should not be null");
- public AddRpc(RouteIdentifierImpl routeId, String actorPath) {
this.routeId = routeId;
this.actorPath = actorPath;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ErrorResponse.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ErrorResponse.java
index ef3f528112..2c26243fe9 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ErrorResponse.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ErrorResponse.java
@@ -7,13 +7,16 @@
*/
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
+
import java.io.Serializable;
public class ErrorResponse implements Serializable {
- Exception exception;
+ private final Exception exception;
- public ErrorResponse(Exception e) {
+ public ErrorResponse(final Exception e) {
+ Preconditions.checkNotNull(e, "Exception should be present for error message");
this.exception = e;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ExecuteRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ExecuteRpc.java
index 030d81ac7e..522dd44f5b 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ExecuteRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/ExecuteRpc.java
@@ -8,16 +8,20 @@
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.common.QName;
import java.io.Serializable;
public class ExecuteRpc implements Serializable {
- private String inputCompositeNode;
- private QName rpc;
+ private final String inputCompositeNode;
+ private final QName rpc;
+
+ public ExecuteRpc(final String inputCompositeNode, final QName rpc) {
+ Preconditions.checkNotNull(inputCompositeNode, "Composite Node input string should be present");
+ Preconditions.checkNotNull(rpc, "rpc Qname should not be null");
- public ExecuteRpc(String inputCompositeNode, QName rpc) {
this.inputCompositeNode = inputCompositeNode;
this.rpc = rpc;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java
index b1fa410e8d..e8d2262182 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpc.java
@@ -9,15 +9,17 @@
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
import java.io.Serializable;
public class GetRoutedRpc implements Serializable {
- RouteIdentifierImpl routeId;
+ private final RouteIdentifierImpl routeId;
- public GetRoutedRpc(RouteIdentifierImpl routeId) {
+ public GetRoutedRpc(final RouteIdentifierImpl routeId) {
+ Preconditions.checkNotNull(routeId, "route id should not be null");
this.routeId = routeId;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java
index 0e1563340b..d426662192 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRoutedRpcReply.java
@@ -12,9 +12,9 @@ import java.io.Serializable;
public class GetRoutedRpcReply implements Serializable {
- private String routePath;
+ private final String routePath;
- public GetRoutedRpcReply(String routePath) {
+ public GetRoutedRpcReply(final String routePath) {
this.routePath = routePath;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java
index c55627961a..c1d4240dca 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpc.java
@@ -7,15 +7,17 @@
*/
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
import java.io.Serializable;
public class GetRpc implements Serializable {
- RouteIdentifierImpl routeId;
+ private final RouteIdentifierImpl routeId;
- public GetRpc(RouteIdentifierImpl routeId) {
+ public GetRpc(final RouteIdentifierImpl routeId) {
+ Preconditions.checkNotNull(routeId, "Route Id should not be null");
this.routeId = routeId;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java
index 3309b989c5..aaf089d16f 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/GetRpcReply.java
@@ -12,9 +12,9 @@ import java.io.Serializable;
public class GetRpcReply implements Serializable {
- private String routePath;
+ private final String routePath;
- public GetRpcReply(String routePath) {
+ public GetRpcReply(final String routePath) {
this.routePath = routePath;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java
index 00ef980bb1..fd73144e1d 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRoutedRpc.java
@@ -7,26 +7,26 @@
*/
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import java.io.Serializable;
public class InvokeRoutedRpc implements Serializable {
- private QName rpc;
- private InstanceIdentifier identifier;
- private CompositeNode input;
+ private final QName rpc;
+ private final YangInstanceIdentifier identifier;
+ private final CompositeNode input;
- public InvokeRoutedRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
- this.rpc = rpc;
- this.identifier = identifier;
- this.input = input;
- }
+ public InvokeRoutedRpc(final QName rpc, final YangInstanceIdentifier identifier, final CompositeNode input) {
+ Preconditions.checkNotNull(rpc, "rpc qname should not be null");
+ Preconditions.checkNotNull(identifier, "instance identifier of routed rpc should not be null");
+ Preconditions.checkNotNull(input, "rpc input should not be null");
- public InvokeRoutedRpc(QName rpc, CompositeNode input) {
this.rpc = rpc;
+ this.identifier = identifier;
this.input = input;
}
@@ -34,7 +34,7 @@ public class InvokeRoutedRpc implements Serializable {
return rpc;
}
- public InstanceIdentifier getIdentifier() {
+ public YangInstanceIdentifier getIdentifier() {
return identifier;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRpc.java
index 1f4eab0971..94b7fe4024 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/InvokeRpc.java
@@ -7,6 +7,7 @@
*/
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -14,10 +15,13 @@ import java.io.Serializable;
public class InvokeRpc implements Serializable {
- private QName rpc;
- private CompositeNode input;
+ private final QName rpc;
+ private final CompositeNode input;
+
+ public InvokeRpc(final QName rpc, final CompositeNode input) {
+ Preconditions.checkNotNull(rpc, "rpc qname should not be null");
+ Preconditions.checkNotNull(input, "rpc input should not be null");
- public InvokeRpc(QName rpc, CompositeNode input) {
this.rpc = rpc;
this.input = input;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java
index a3aa9d12fa..b560b8c8c0 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRoutedRpc.java
@@ -8,6 +8,7 @@
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import java.io.Serializable;
@@ -15,10 +16,13 @@ import java.util.Set;
public class RemoveRoutedRpc implements Serializable {
- Set> announcements;
- String actorPath;
+ private final Set> announcements;
+ private final String actorPath;
+
+ public RemoveRoutedRpc(final Set> announcements, final String actorPath) {
+ Preconditions.checkNotNull(announcements, "Route identifier should not be null");
+ Preconditions.checkNotNull(actorPath, "Actor path should not be null");
- public RemoveRoutedRpc(Set> announcements, String actorPath) {
this.announcements = announcements;
this.actorPath = actorPath;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java
index 0bfd78aaae..289334fccc 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RemoveRpc.java
@@ -8,15 +8,18 @@
package org.opendaylight.controller.remote.rpc.messages;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
import java.io.Serializable;
public class RemoveRpc implements Serializable {
- RouteIdentifierImpl routeId;
+ private final RouteIdentifierImpl routeId;
+
+ public RemoveRpc(final RouteIdentifierImpl routeId) {
+ Preconditions.checkNotNull(routeId, "Route Id should not be null");
- public RemoveRpc(RouteIdentifierImpl routeId) {
this.routeId = routeId;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java
index 132fdba054..c57a258426 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RoutingTableData.java
@@ -15,11 +15,11 @@ import java.util.LinkedHashSet;
import java.util.Map;
public class RoutingTableData implements Serializable {
- private Map, String> rpcMap;
- private Map, LinkedHashSet> routedRpcMap;
+ private final Map, String> rpcMap;
+ private final Map, LinkedHashSet> routedRpcMap;
- public RoutingTableData(Map, String> rpcMap,
- Map, LinkedHashSet> routedRpcMap) {
+ public RoutingTableData(final Map, String> rpcMap,
+ final Map, LinkedHashSet> routedRpcMap) {
this.rpcMap = rpcMap;
this.routedRpcMap = routedRpcMap;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RpcResponse.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RpcResponse.java
index cbfecb1918..17766f15b9 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RpcResponse.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/RpcResponse.java
@@ -12,9 +12,9 @@ package org.opendaylight.controller.remote.rpc.messages;
import java.io.Serializable;
public class RpcResponse implements Serializable {
- private String resultCompositeNode;
+ private final String resultCompositeNode;
- public RpcResponse(String resultCompositeNode) {
+ public RpcResponse(final String resultCompositeNode) {
this.resultCompositeNode = resultCompositeNode;
}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/UpdateSchemaContext.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/UpdateSchemaContext.java
new file mode 100644
index 0000000000..83fc7723b3
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/messages/UpdateSchemaContext.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 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.controller.remote.rpc.messages;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class UpdateSchemaContext {
+
+ private final SchemaContext schemaContext;
+
+ public UpdateSchemaContext(final SchemaContext schemaContext) {
+ this.schemaContext = schemaContext;
+ }
+
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistry.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistry.java
index 7cb505aa98..e36060cc13 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistry.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/registry/RpcRegistry.java
@@ -14,6 +14,7 @@ import akka.cluster.ClusterEvent;
import akka.cluster.Member;
import akka.japi.Creator;
import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
+import org.opendaylight.controller.remote.rpc.ActorConstants;
import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
import org.opendaylight.controller.remote.rpc.messages.AddRpc;
import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
@@ -171,7 +172,7 @@ public class RpcRegistry extends AbstractUntypedActor {
}
if(i == index) {
if(!currentNodeAddress.equals(member.address())) {
- actor = this.context().actorSelection(member.address() + "/user/rpc-registry");
+ actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
break;
} else if(index < memberSize-1){ // pick the next element in the set
index++;
@@ -180,7 +181,7 @@ public class RpcRegistry extends AbstractUntypedActor {
i++;
}
if(actor == null && previousMember != null) {
- actor = this.context().actorSelection(previousMember.address() + "/user/rpc-registry");
+ actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
}
}
return actor;
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorUtil.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/ActorUtil.java
similarity index 97%
rename from opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorUtil.java
rename to opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/ActorUtil.java
index 13324f996e..8f60eabf5f 100644
--- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/ActorUtil.java
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/ActorUtil.java
@@ -6,7 +6,7 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
*/
-package org.opendaylight.controller.remote.rpc;
+package org.opendaylight.controller.remote.rpc.utils;
import akka.actor.ActorRef;
import akka.actor.ActorSelection;
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/InstanceIdentifierForXmlCodec.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/InstanceIdentifierForXmlCodec.java
new file mode 100644
index 0000000000..92a7fbae79
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/InstanceIdentifierForXmlCodec.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2014 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.controller.remote.rpc.utils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class InstanceIdentifierForXmlCodec {
+ private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
+ private static final Splitter SLASH_SPLITTER = Splitter.on('/');
+ private static final Splitter COLON_SPLITTER = Splitter.on(':');
+ private static final Splitter AT_SPLITTER = Splitter.on('@');
+ private static final Logger logger = LoggerFactory.getLogger(InstanceIdentifierForXmlCodec.class);
+
+ private InstanceIdentifierForXmlCodec() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ public static YangInstanceIdentifier deserialize(final Element element, final SchemaContext schemaContext) {
+ Preconditions.checkNotNull(element, "Value of element for deserialization can't be null");
+ Preconditions.checkNotNull(schemaContext,
+ "Schema context for deserialization of instance identifier type can't be null");
+
+ final String valueTrimmed = element.getTextContent().trim();
+ logger.debug("Instance identifier derserialize: splitting the text {} with Slash to find path arguments", valueTrimmed);
+ final Iterator xPathParts = SLASH_SPLITTER.split(valueTrimmed).iterator();
+
+ // must be at least "/pr:node"
+ if (!xPathParts.hasNext() || !xPathParts.next().isEmpty() || !xPathParts.hasNext()) {
+ logger.debug("Instance identifier derserialize: No path argument found for element.");
+ return null;
+ }
+
+ List result = new ArrayList<>();
+ while (xPathParts.hasNext()) {
+ String xPathPartTrimmed = xPathParts.next().trim();
+
+ PathArgument pathArgument = toPathArgument(xPathPartTrimmed, element, schemaContext);
+ if (pathArgument != null) {
+ result.add(pathArgument);
+ }
+ }
+ return YangInstanceIdentifier.create(result);
+ }
+
+ public static Element serialize(final YangInstanceIdentifier id, final Element element) {
+ Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
+ Preconditions.checkNotNull(element, "DOM element can't be null");
+
+ final RandomPrefix prefixes = new RandomPrefix();
+ final String str = XmlUtils.encodeIdentifier(prefixes, id);
+
+ for (Entry e: prefixes.getPrefixes()) {
+ element.setAttribute("xmlns:" + e.getValue(), e.getKey().toString());
+ }
+ element.setTextContent(str);
+ return element;
+ }
+
+ private static String getIdAndPrefixAsStr(final String pathPart) {
+ int predicateStartIndex = pathPart.indexOf('[');
+ return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
+ }
+
+ private static PathArgument toPathArgument(final String xPathArgument, final Element element, final SchemaContext schemaContext) {
+ final QName mainQName = toIdentity(xPathArgument, element, schemaContext);
+
+ // predicates
+ final Matcher matcher = PREDICATE_PATTERN.matcher(xPathArgument);
+ final Map predicates = new HashMap<>();
+ QName currentQName = mainQName;
+
+ while (matcher.find()) {
+ final String predicateStr = matcher.group(1).trim();
+ final int indexOfEqualityMark = predicateStr.indexOf('=');
+ if (indexOfEqualityMark != -1) {
+ final Object predicateValue = toPredicateValue(predicateStr.substring(indexOfEqualityMark + 1));
+ if (predicateValue == null) {
+ return null;
+ }
+
+ if (predicateStr.charAt(0) != '.') {
+ // target is not a leaf-list
+ currentQName = toIdentity(predicateStr.substring(0, indexOfEqualityMark), element, schemaContext);
+ if (currentQName == null) {
+ return null;
+ }
+ }
+ logger.debug("Instance identifier derserialize: finding predicates of node {}", predicateValue);
+ predicates.put(currentQName, predicateValue);
+ }
+ }
+
+ if (predicates.isEmpty()) {
+ return new YangInstanceIdentifier.NodeIdentifier(mainQName);
+ } else {
+ return new YangInstanceIdentifier.NodeIdentifierWithPredicates(mainQName, predicates);
+ }
+
+ }
+
+ public static QName toIdentity(final String xPathArgument, final Element element, final SchemaContext schemaContext) {
+ final String xPathPartTrimmed = getIdAndPrefixAsStr(xPathArgument).trim();
+ final Iterator it = COLON_SPLITTER.split(xPathPartTrimmed).iterator();
+
+ // Empty string
+ if (!it.hasNext()) {
+ return null;
+ }
+
+ final String prefix = it.next().trim();
+ if (prefix.isEmpty()) {
+ return null;
+ }
+
+ // it is not "prefix:value"
+ if (!it.hasNext()) {
+ return null;
+ }
+
+ final String identifier = it.next().trim();
+ if (identifier.isEmpty()) {
+ return null;
+ }
+
+ URI namespace = null;
+ String namespaceStr = null;
+ try {
+ namespaceStr = element.getAttribute("xmlns:"+prefix);
+ namespace = new URI(namespaceStr);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("It wasn't possible to convert " + namespaceStr + " to URI object.");
+ } catch (NullPointerException e) {
+ throw new IllegalArgumentException("I wasn't possible to get namespace for prefix " + prefix);
+ }
+
+ Module module = schemaContext.findModuleByNamespaceAndRevision(namespace, null);
+ return QName.create(module.getQNameModule(), identifier);
+ }
+
+ private static String trimIfEndIs(final String str, final char end) {
+ final int l = str.length() - 1;
+ if (str.charAt(l) != end) {
+ return null;
+ }
+
+ return str.substring(1, l);
+ }
+
+ private static Object toPredicateValue(final String predicatedValue) {
+ logger.debug("Instance identifier derserialize: converting the predicate vstring to object {}", predicatedValue);
+ final String predicatedValueTrimmed = predicatedValue.trim();
+ if (predicatedValue.isEmpty()) {
+ return null;
+ }
+ String updatedValue = null;
+ switch (predicatedValueTrimmed.charAt(0)) {
+ case '"':
+ updatedValue = trimIfEndIs(predicatedValueTrimmed, '"');
+ break;
+ case '\'':
+ updatedValue = trimIfEndIs(predicatedValueTrimmed, '\'');
+ break;
+ default:
+ updatedValue = predicatedValueTrimmed;
+ }
+ Iterator it = AT_SPLITTER.split(updatedValue).iterator();
+ // Empty string
+ if (!it.hasNext()) {
+ return null;
+ }
+
+ final String value = it.next().trim();
+ if (value.isEmpty()) {
+ return null;
+ }
+
+ if (!it.hasNext()) {
+ return value;
+ }
+
+ final String type = it.next().trim();
+ if (type.isEmpty()) {
+ return value;
+ }
+ Object predicateObject = null;
+ try {
+ logger.debug("Instance identifier derserialize: converting the predicate value {{}}to correct object type {{}}", value, type);
+ predicateObject = Class.forName(type).getConstructor(String.class).newInstance(value);
+ } catch (Exception e) {
+ logger.error("Could not convert to valid type of value", e);
+ }
+ return predicateObject;
+ }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RandomPrefix.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RandomPrefix.java
new file mode 100644
index 0000000000..55cc8192a8
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/RandomPrefix.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 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.controller.remote.rpc.utils;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Picked from Yang tools because it was not public class
+ */
+
+final class RandomPrefix {
+ final Map prefixes = new HashMap<>();
+
+ Iterable> getPrefixes() {
+ return prefixes.entrySet();
+ }
+
+ String encodeQName(final QName qname) {
+ String prefix = prefixes.get(qname.getNamespace());
+ if (prefix == null) {
+ prefix = qname.getPrefix();
+ if (prefix == null || prefix.isEmpty() || prefixes.containsValue(prefix)) {
+ final ThreadLocalRandom random = ThreadLocalRandom.current();
+ do {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 4; i++) {
+ sb.append((char)('a' + random.nextInt(25)));
+ }
+
+ prefix = sb.toString();
+ } while (prefixes.containsValue(prefix));
+ }
+
+ prefixes.put(qname.getNamespace(), prefix);
+ }
+
+ return prefix + ':' + qname.getLocalName();
+ }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlDocumentUtils.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlDocumentUtils.java
new file mode 100644
index 0000000000..127aa0732b
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlDocumentUtils.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2013 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.controller.remote.rpc.utils;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import javax.activation.UnsupportedDataTypeException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.dom.DOMResult;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkState;
+
+public class XmlDocumentUtils {
+ private static class ElementWithSchemaContext {
+ Element element;
+ SchemaContext schemaContext;
+
+ ElementWithSchemaContext(final Element element,final SchemaContext schemaContext) {
+ this.schemaContext = schemaContext;
+ this.element = element;
+ }
+
+ Element getElement() {
+ return element;
+ }
+
+ SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+ }
+
+ public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
+ private static final Logger logger = LoggerFactory.getLogger(XmlDocumentUtils.class);
+ private static final XMLOutputFactory FACTORY = XMLOutputFactory.newFactory();
+
+ /**
+ * Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding
+ * Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will
+ * be transformed to root in XML Document. Each element of Data DOM tree is compared against specified Data
+ * Node Container Schema and transformed accordingly.
+ *
+ * @param data Data DOM root element
+ * @param schema Data Node Container Schema
+ * @param codecProvider XML Codec Provider
+ * @return new instance of XML Document
+ * @throws javax.activation.UnsupportedDataTypeException
+ */
+ public static Document toDocument(final CompositeNode data, final DataNodeContainer schema, final XmlCodecProvider codecProvider)
+ throws UnsupportedDataTypeException {
+ Preconditions.checkNotNull(data);
+ Preconditions.checkNotNull(schema);
+
+ if (!(schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode)) {
+ throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
+ }
+
+ final DOMResult result = new DOMResult(getDocument());
+ try {
+ final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
+ XmlStreamUtils.create(codecProvider).writeDocument(writer, data, (SchemaNode)schema);
+ writer.close();
+ return (Document)result.getNode();
+ } catch (XMLStreamException e) {
+ logger.error("Failed to serialize data {}", data, e);
+ return null;
+ }
+ }
+
+ public static Document getDocument() {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ Document doc = null;
+ try {
+ DocumentBuilder bob = dbf.newDocumentBuilder();
+ doc = bob.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ return doc;
+ }
+
+
+ public static QName qNameFromElement(final Element xmlElement) {
+ String namespace = xmlElement.getNamespaceURI();
+ String localName = xmlElement.getLocalName();
+ return QName.create(namespace != null ? URI.create(namespace) : null, null, localName);
+ }
+
+ private static Node> toNodeWithSchema(final Element xmlElement, final DataSchemaNode schema, final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
+ checkQName(xmlElement, schema.getQName());
+ if (schema instanceof DataNodeContainer) {
+ return toCompositeNodeWithSchema(xmlElement, schema.getQName(), (DataNodeContainer) schema, schemaCtx);
+ } else if (schema instanceof LeafSchemaNode) {
+ return toSimpleNodeWithType(xmlElement, (LeafSchemaNode) schema, codecProvider,schemaCtx);
+ } else if (schema instanceof LeafListSchemaNode) {
+ return toSimpleNodeWithType(xmlElement, (LeafListSchemaNode) schema, codecProvider,schemaCtx);
+ }
+ return null;
+ }
+
+
+
+ private static Node> toSimpleNodeWithType(final Element xmlElement, final LeafSchemaNode schema,
+ final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
+ TypeDefinitionAwareCodec extends Object, ? extends TypeDefinition>> codec = codecProvider.codecFor(schema.getType());
+ String text = xmlElement.getTextContent();
+ Object value = null;
+ if (codec != null) {
+ logger.debug("toSimpleNodeWithType: found codec, deserializing text {}", text);
+ value = codec.deserialize(text);
+ }
+
+ final TypeDefinition> baseType = XmlUtils.resolveBaseTypeFrom(schema.getType());
+ if (baseType instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) {
+ logger.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
+ value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
+
+ } else if(baseType instanceof IdentityrefTypeDefinition){
+ logger.debug("toSimpleNodeWithType: base type of node is IdentityrefTypeDefinition, deserializing element", xmlElement);
+ value = InstanceIdentifierForXmlCodec.toIdentity(xmlElement.getTextContent(), xmlElement, schemaCtx);
+
+ }
+
+ if (value == null) {
+ logger.debug("toSimpleNodeWithType: no type found for element, returning just the text string value of element {}", xmlElement);
+ value = xmlElement.getTextContent();
+ }
+
+ Optional modifyAction = getModifyOperationFromAttributes(xmlElement);
+ return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull());
+ }
+
+ private static Node> toSimpleNodeWithType(final Element xmlElement, final LeafListSchemaNode schema,
+ final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
+ TypeDefinitionAwareCodec extends Object, ? extends TypeDefinition>> codec = codecProvider.codecFor(schema.getType());
+ String text = xmlElement.getTextContent();
+ Object value = null;
+ if (codec != null) {
+ logger.debug("toSimpleNodeWithType: found codec, deserializing text {}", text);
+ value = codec.deserialize(text);
+ }
+
+ if (schema.getType() instanceof org.opendaylight.yangtools.yang.model.util.InstanceIdentifier) {
+ logger.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
+ value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
+ }
+
+ if (value == null) {
+ logger.debug("toSimpleNodeWithType: no type found for element, returning just the text string value of element {}", xmlElement);
+ value = xmlElement.getTextContent();
+ }
+
+ Optional modifyAction = getModifyOperationFromAttributes(xmlElement);
+ return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull());
+ }
+
+ private static Node> toCompositeNodeWithSchema(final Element xmlElement, final QName qName, final DataNodeContainer schema,
+ final SchemaContext schemaCtx) {
+ List> values = toDomNodes(xmlElement, Optional.fromNullable(schema.getChildNodes()),schemaCtx);
+ Optional modifyAction = getModifyOperationFromAttributes(xmlElement);
+ return ImmutableCompositeNode.create(qName, values, modifyAction.orNull());
+ }
+
+ private static Optional getModifyOperationFromAttributes(final Element xmlElement) {
+ Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName());
+ if(attributeNodeNS == null) {
+ return Optional.absent();
+ }
+
+ ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue());
+ Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement);
+
+ return Optional.of(action);
+ }
+
+ private static void checkQName(final Element xmlElement, final QName qName) {
+ checkState(Objects.equal(xmlElement.getNamespaceURI(), qName.getNamespace().toString()));
+ checkState(qName.getLocalName().equals(xmlElement.getLocalName()));
+ }
+
+ public static final Optional findFirstSchema(final QName qname, final Collection dataSchemaNode) {
+ if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
+ for (DataSchemaNode dsn : dataSchemaNode) {
+ if (qname.isEqualWithoutRevision(dsn.getQName())) {
+ return Optional. of(dsn);
+ } else if (dsn instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+ Optional foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
+ if (foundDsn != null && foundDsn.isPresent()) {
+ return foundDsn;
+ }
+ }
+ }
+ }
+ }
+ return Optional.absent();
+ }
+
+ private static Node> toDomNode(Element element) {
+ QName qname = qNameFromElement(element);
+
+ ImmutableList.Builder> values = ImmutableList.> builder();
+ NodeList nodes = element.getChildNodes();
+ boolean isSimpleObject = true;
+ String value = null;
+ for (int i = 0; i < nodes.getLength(); i++) {
+ org.w3c.dom.Node child = nodes.item(i);
+ if (child instanceof Element) {
+ isSimpleObject = false;
+ values.add(toDomNode((Element) child));
+ }
+ if (isSimpleObject && child instanceof org.w3c.dom.Text) {
+ value = element.getTextContent();
+ if (!Strings.isNullOrEmpty(value)) {
+ isSimpleObject = true;
+ }
+ }
+ }
+ if (isSimpleObject) {
+ return new SimpleNodeTOImpl<>(qname, null, value);
+ }
+ return ImmutableCompositeNode.create(qname, values.build());
+ }
+
+ public static List> toDomNodes(final Element element, final Optional> context,SchemaContext schemaCtx) {
+ return forEachChild(element.getChildNodes(),schemaCtx, new Function>>() {
+
+ @Override
+ public Optional> apply(ElementWithSchemaContext input) {
+ if (context.isPresent()) {
+ QName partialQName = qNameFromElement(input.getElement());
+ Optional schemaNode = XmlDocumentUtils.findFirstSchema(partialQName, context.get());
+ if (schemaNode.isPresent()) {
+ return Optional.> fromNullable(//
+ toNodeWithSchema(input.getElement(), schemaNode.get(), XmlDocumentUtils.defaultValueCodecProvider(),input.getSchemaContext()));
+ }
+ }
+ return Optional.> fromNullable(toDomNode(input.getElement()));
+ }
+
+ });
+
+ }
+
+ private static final List forEachChild(final NodeList nodes, final SchemaContext schemaContext, final Function> forBody) {
+ final int l = nodes.getLength();
+ if (l == 0) {
+ return ImmutableList.of();
+ }
+
+ final List list = new ArrayList<>(l);
+ for (int i = 0; i < l; i++) {
+ org.w3c.dom.Node child = nodes.item(i);
+ if (child instanceof Element) {
+ Optional result = forBody.apply(new ElementWithSchemaContext((Element) child,schemaContext));
+ if (result.isPresent()) {
+ list.add(result.get());
+ }
+ }
+ }
+ return ImmutableList.copyOf(list);
+ }
+
+ public static final XmlCodecProvider defaultValueCodecProvider() {
+ return XmlUtils.DEFAULT_XML_CODEC_PROVIDER;
+ }
+}
diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlStreamUtils.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlStreamUtils.java
new file mode 100644
index 0000000000..e4576c445b
--- /dev/null
+++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/remote/rpc/utils/XmlStreamUtils.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2014 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.controller.remote.rpc.utils;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.Map.Entry;
+
+/**
+ * Utility class for bridging JAXP Stream and YANG Data APIs. Note that the definition of this class
+ * by no means final and subject to change as more functionality is centralized here.
+ */
+@Beta
+public class XmlStreamUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(XmlStreamUtils.class);
+ private final XmlCodecProvider codecProvider;
+
+ protected XmlStreamUtils(final XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ /**
+ * Create a new instance encapsulating a particular codec provider.
+ *
+ * @param codecProvider XML codec provider
+ * @return A new instance
+ */
+ public static XmlStreamUtils create(final XmlCodecProvider codecProvider) {
+ return new XmlStreamUtils(codecProvider);
+ }
+
+ /**
+ * Check if a particular data element can be emitted as an empty element, bypassing value encoding. This
+ * functionality is optional, as valid XML stream is produced even if start/end element is produced unconditionally.
+ *
+ * @param data Data node
+ * @return True if the data node will result in empty element body.
+ */
+ public static boolean isEmptyElement(final Node> data) {
+ if (data == null) {
+ return true;
+ }
+
+ if (data instanceof CompositeNode) {
+ return ((CompositeNode) data).getValue().isEmpty();
+ }
+ if (data instanceof SimpleNode) {
+ return data.getValue() == null;
+ }
+
+ // Safe default
+ return false;
+ }
+
+ /**
+ * Write an InstanceIdentifier into the output stream. Calling corresponding {@link javax.xml.stream.XMLStreamWriter#writeStartElement(String)}
+ * and {@link javax.xml.stream.XMLStreamWriter#writeEndElement()} is the responsibility of the caller.
+ *
+ * @param writer XML Stream writer
+ * @param id InstanceIdentifier
+ * @throws javax.xml.stream.XMLStreamException
+ */
+ public static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull YangInstanceIdentifier id) throws XMLStreamException {
+ Preconditions.checkNotNull(writer, "Writer may not be null");
+ Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
+ LOG.debug("Writing Instance identifier with Random prefix");
+ final RandomPrefix prefixes = new RandomPrefix();
+ final String str = XmlUtils.encodeIdentifier(prefixes, id);
+
+ for (Entry e: prefixes.getPrefixes()) {
+ writer.writeNamespace(e.getValue(), e.getKey().toString());
+ }
+ LOG.debug("Instance identifier with Random prefix is now {}", str);
+ writer.writeCharacters(str);
+ }
+
+ /**
+ * Write a full XML document corresponding to a CompositeNode into an XML stream writer.
+ *
+ * @param writer XML Stream writer
+ * @param data data node
+ * @param schema corresponding schema node, may be null
+ * @throws javax.xml.stream.XMLStreamException if an encoding problem occurs
+ */
+ public void writeDocument(final @Nonnull XMLStreamWriter writer, final @Nonnull CompositeNode data, final @Nullable SchemaNode schema) throws XMLStreamException {
+ // final Boolean repairing = (Boolean) writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
+ // Preconditions.checkArgument(repairing == true, "XML Stream Writer has to be repairing namespaces");
+
+ writer.writeStartDocument();
+ writeElement(writer, data, schema);
+ writer.writeEndDocument();
+ writer.flush();
+ }
+
+
+ /**
+ * Write an element into a XML stream writer. This includes the element start/end tags and
+ * the value of the element.
+ *
+ * @param writer XML Stream writer
+ * @param data data node
+ * @param schema Schema node
+ * @throws javax.xml.stream.XMLStreamException if an encoding problem occurs
+ */
+ public void writeElement(final XMLStreamWriter writer, final @Nonnull Node> data, final SchemaNode schema) throws XMLStreamException {
+ final QName qname = data.getNodeType();
+ final String pfx = qname.getPrefix() != null ? qname.getPrefix() : "";
+ final String ns = qname.getNamespace() != null ? qname.getNamespace().toString() : "";
+
+ if (isEmptyElement(data)) {
+ writer.writeEmptyElement(pfx, qname.getLocalName(), ns);
+ return;
+ }
+
+ writer.writeStartElement(pfx, qname.getLocalName(), ns);
+ if (data instanceof AttributesContainer && ((AttributesContainer) data).getAttributes() != null) {
+ for (Entry attribute : ((AttributesContainer) data).getAttributes().entrySet()) {
+ writer.writeAttribute(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), attribute.getValue());
+ }
+ }
+
+ if (data instanceof SimpleNode>) {
+ LOG.debug("writeElement : node is of type SimpleNode");
+ // Simple node
+ if (schema instanceof LeafListSchemaNode) {
+ writeValue(writer, ((LeafListSchemaNode) schema).getType(), data.getValue());
+ } else if (schema instanceof LeafSchemaNode) {
+ writeValue(writer, ((LeafSchemaNode) schema).getType(), data.getValue());
+ } else {
+ Object value = data.getValue();
+ if (value != null) {
+ writer.writeCharacters(String.valueOf(value));
+ }
+ }
+ } else {
+ LOG.debug("writeElement : node is of type CompositeNode");
+ // CompositeNode
+ for (Node> child : ((CompositeNode) data).getValue()) {
+ DataSchemaNode childSchema = null;
+ if (schema instanceof DataNodeContainer) {
+ childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
+ if (childSchema == null) {
+ LOG.debug("Probably the data node \"{}\" does not conform to schema", child == null ? "" : child.getNodeType().getLocalName());
+ }
+ }
+
+ writeElement(writer, child, childSchema);
+ }
+ }
+
+ writer.writeEndElement();
+ }
+
+ /**
+ * Write a value into a XML stream writer. This method assumes the start and end of element is
+ * emitted by the caller.
+ *
+ * @param writer XML Stream writer
+ * @param type type definitions
+ * @param value object value
+ * @throws javax.xml.stream.XMLStreamException if an encoding problem occurs
+ */
+ public void writeValue(final @Nonnull XMLStreamWriter writer, final @Nonnull TypeDefinition> type, final Object value) throws XMLStreamException {
+ if (value == null) {
+ LOG.debug("Value of {}:{} is null, not encoding it", type.getQName().getNamespace(), type.getQName().getLocalName());
+ return;
+ }
+
+ final TypeDefinition> baseType = XmlUtils.resolveBaseTypeFrom(type);
+ if (baseType instanceof IdentityrefTypeDefinition) {
+ write(writer, (IdentityrefTypeDefinition) baseType, value);
+ } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
+ write(writer, (InstanceIdentifierTypeDefinition) baseType, value);
+ } else {
+ final TypeDefinitionAwareCodec