<bundle>mvn:org.opendaylight.controller/threadpool-config-api/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/threadpool-config-impl/${project.version}</bundle>
<feature version='${project.version}'>odl-config-startup</feature>
+ <configfile finalname="configuration/initial/00-netty.xml">mvn:org.opendaylight.controller/config-netty-config/${config.version}/xml/config</configfile>
</feature>
</features>
\ No newline at end of file
<artifactId>sal-rest-connector-config</artifactId>
<version>${mdsal.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-netty-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>md-sal-config</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-config</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-connector-config</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-rest-docgen</artifactId>
<artifactId>sample-toaster-provider</artifactId>
<version>${mdsal.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.samples</groupId>
+ <artifactId>toaster-config</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>com.sun.jersey.jersey-servlet</artifactId>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-subsystem</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </parent>
+ <artifactId>config-netty-config</artifactId>
+ <description>Configuration files for sal-rest-connector</description>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/00-netty.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<module>shutdown-impl</module>
<module>netconf-config-dispatcher</module>
<module>config-module-archetype</module>
+ <module>config-netty-config</module>
</modules>
<dependencies>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/configuration</outputDirectory>
- <includeArtifactIds>sal-rest-connector-config</includeArtifactIds>
+ <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config</includeArtifactIds>
<includes>**\/*.xml</includes>
<excludeTransitive>true</excludeTransitive>
<ignorePermissions>false</ignorePermissions>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-rest-connector-config</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-netty-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>md-sal-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-connector-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.samples</groupId>
+ <artifactId>toaster-config</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-rest-docgen</artifactId>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/configuration</outputDirectory>
- <includeArtifactIds>sal-rest-connector-config</includeArtifactIds>
+ <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config</includeArtifactIds>
<includes>**\/*.xml</includes>
<excludeTransitive>true</excludeTransitive>
<ignorePermissions>false</ignorePermissions>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-parent</artifactId>
+ <version>1.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>md-sal-config</artifactId>
+ <description>Configuration files for md-sal</description>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/01-md-sal.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<module>sal-binding-util</module>
+ <!-- Configuration File -->
+ <module>md-sal-config</module>
+
<!-- Samples -->
<module>samples</module>
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;
private long persistIdentifier = 1;
- public ExampleActor(String id, Map<String, String> peerAddresses) {
- super(id, peerAddresses);
+ public ExampleActor(String id, Map<String, String> peerAddresses,
+ Optional<ConfigParams> configParams) {
+ super(id, peerAddresses, configParams);
}
- public static Props props(final String id, final Map<String, String> peerAddresses){
+ public static Props props(final String id, final Map<String, String> peerAddresses,
+ final Optional<ConfigParams> configParams){
return Props.create(new Creator<ExampleActor>(){
@Override public ExampleActor create() throws Exception {
- return new ExampleActor(id, peerAddresses);
+ return new ExampleActor(id, peerAddresses, configParams);
}
});
}
}
} 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);
}
@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) {
--- /dev/null
+/*
+ * 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;
+ }
+}
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;
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.<ConfigParams>absent()), "example-1");
ActorRef example2Actor =
actorSystem.actorOf(ExampleActor.props("example-2",
- withoutPeer("example-2")), "example-2");
+ withoutPeer("example-2"), Optional.<ConfigParams>absent()), "example-2");
ActorRef example3Actor =
actorSystem.actorOf(ExampleActor.props("example-3",
- withoutPeer("example-3")), "example-3");
+ withoutPeer("example-3"), Optional.<ConfigParams>absent()), "example-3");
List<ActorRef> examples = Arrays.asList(example1Actor, example2Actor, example3Actor);
String actorName = "example-" + i;
examples.add(i - 1,
actorSystem.actorOf(ExampleActor.props(actorName,
- withoutPeer(actorName)), actorName));
+ withoutPeer(actorName), Optional.<ConfigParams>absent()),
+ actorName));
System.out.println("Created actor : " + actorName);
continue;
}
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;
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 {
private static Map<String, String> allPeers = new HashMap<>();
private static Map<String, ActorRef> clientActorRefs = new HashMap<String, ActorRef>();
private static Map<String, ActorRef> actorRefs = new HashMap<String, ActorRef>();
- 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.
* createNodes:{num}
* addNodes:{num}
* stopNode:{nodeName}
+ * reinstateNode:{nodeName}
* addClients:{num}
* addClientsToNode:{nodeName, num}
* startLogging
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();
}
}
+ 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);
public void addNodes(int num) {
Map<String, String> 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<String, ActorRef> newActorRefs = new HashMap<String, ActorRef>(num);
for (Map.Entry<String, String> 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
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);
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<String,ActorRef> entry : clientActorRefs.entrySet()) {
+ if (entry.getKey().endsWith(actorName)) {
+ actorSystem.stop(entry.getValue());
+ }
}
+
actorSystem.stop(actorRef);
actorRefs.remove(actorName);
}
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() {
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<String, String> withoutPeer(String peerId) {
Map<String, String> without = new ConcurrentHashMap<>(allPeers);
--- /dev/null
+/*
+ * 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<ReplicatedLogEntry> journal;
+ protected final Object snapshot;
+ protected long snapshotIndex = -1;
+ protected long snapshotTerm = -1;
+
+ public AbstractReplicatedLogImpl(Object state, long snapshotIndex,
+ long snapshotTerm, List<ReplicatedLogEntry> 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<ReplicatedLogEntry> getFrom(long logEntryIndex) {
+ int adjustedIndex = adjustedIndex(logEntryIndex);
+ int size = journal.size();
+ List<ReplicatedLogEntry> 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);
+}
--- /dev/null
+/*
+ * 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
+ * <p/>
+ * 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();
+}
--- /dev/null
+/*
+ * 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
+ * <p/>
+ * 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;
+ }
+}
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;
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;
public RaftActor(String id, Map<String, String> peerAddresses) {
+ this(id, peerAddresses, Optional.<ConfigParams>absent());
+ }
+
+ public RaftActor(String id, Map<String, String> peerAddresses,
+ Optional<ConfigParams> 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();
// 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());
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);
}
}
}
}
+ public java.util.Set<String> getPeers() {
+ return context.getPeerAddresses().keySet();
+ }
+
+ protected String getReplicatedLogState() {
+ return "snapshotIndex=" + context.getReplicatedLog().getSnapshotIndex()
+ + ", snapshotTerm=" + context.getReplicatedLog().getSnapshotTerm()
+ + ", im-mem journal size=" + context.getReplicatedLog().size();
+ }
/**
}
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<ReplicatedLogEntry> 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<>();
+ super();
}
- @Override public ReplicatedLogEntry get(long index) {
- int adjustedIndex = adjustedIndex(index);
+ @Override public void removeFromAndPersist(long logEntryIndex) {
+ int adjustedIndex = adjustedIndex(logEntryIndex);
- 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();
- }
-
-
- @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;
}
//FIXME : Doing nothing for now
}
});
-
-
- }
-
- @Override public void append(
- final ReplicatedLogEntry replicatedLogEntry) {
- journal.add(replicatedLogEntry);
- }
-
- @Override public List<ReplicatedLogEntry> getFrom(long index) {
- int adjustedIndex = adjustedIndex(index);
-
- List<ReplicatedLogEntry> 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(
new Procedure<ReplicatedLogEntry>() {
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) {
);
}
- @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;
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 {
*/
void setLastApplied(long lastApplied);
+ /**
+ *
+ * @param replicatedLog
+ */
+ public void setReplicatedLog(ReplicatedLog replicatedLog);
+
/**
* @return A representation of the log
*/
* @param peerAddress
*/
void setPeerAddress(String peerId, String peerAddress);
+
+ /**
+ * @return ConfigParams
+ */
+ public ConfigParams getConfigParams();
}
import static com.google.common.base.Preconditions.checkState;
-public class RaftActorContextImpl implements RaftActorContext{
+public class RaftActorContextImpl implements RaftActorContext {
private final ActorRef actor;
private long lastApplied;
- private final ReplicatedLog replicatedLog;
+ private ReplicatedLog replicatedLog;
private final Map<String, String> 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<String, String> peerAddresses, LoggingAdapter logger) {
+ long lastApplied, ReplicatedLog replicatedLog,
+ Map<String, String> peerAddresses, ConfigParams configParams,
+ LoggingAdapter logger) {
this.actor = actor;
this.context = context;
this.id = id;
this.lastApplied = lastApplied;
this.replicatedLog = replicatedLog;
this.peerAddresses = peerAddresses;
+ this.configParams = configParams;
this.LOG = logger;
}
this.lastApplied = lastApplied;
}
+ @Override public void setReplicatedLog(ReplicatedLog replicatedLog) {
+ this.replicatedLog = replicatedLog;
+ }
+
@Override public ReplicatedLog getReplicatedLog() {
return replicatedLog;
}
return peerAddresses.get(peerId);
}
+ @Override public ConfigParams getConfigParams() {
+ return configParams;
+ }
+
@Override public void addToPeers(String name, String address) {
peerAddresses.put(name, address);
}
*/
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
- * <p/>
- * 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;
-
/**
*
*/
* @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));
}
/**
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
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())
);
}
(InstallSnapshotReply) message);
}
} finally {
- scheduleHeartBeat(HEART_BEAT_INTERVAL);
+ scheduleHeartBeat(context.getConfigParams().getHeartBeatInterval());
}
return super.handleMessage(sender, message);
--- /dev/null
+/*
+ * 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<ReplicatedLogEntry> 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<ReplicatedLogEntry> getEntriesTill(int index) {
+ return journal.subList(0, index);
+ }
+ }
+}
this.peerAddresses = peerAddresses;
}
-
+ @Override
+ public ConfigParams getConfigParams() {
+ return new DefaultConfigParamsImpl();
+ }
public static class SimpleReplicatedLog implements ReplicatedLog {
private final List<ReplicatedLogEntry> log = new ArrayList<>();
--- /dev/null
+/*
+ * 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";
+}
SchemaService schemaService = brokerSession.getService(SchemaService.class);
schemaContext = schemaService.getGlobalContext();
- rpcManager = actorSystem.actorOf(RpcManager.props(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry), "rpc");
+ rpcManager = actorSystem.actorOf(RpcManager.props(clusterWrapper, schemaContext, brokerSession, rpcProvisionRegistry), ActorConstants.RPC_MANAGER);
LOG.debug("Rpc actors are created.");
}
private void createRpcActors() {
LOG.debug("Create rpc registry and broker actors");
- rpcRegistry = getContext().actorOf(RpcRegistry.props(clusterWrapper), "rpc-registry");
- rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), "rpc-broker");
+ 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() + "/user/rpc/rpc-broker";
+ String rpcBrokerPath = clusterWrapper.getAddress().toString() + ActorConstants.RPC_BROKER_PATH;
rpcListener = new RpcListener(rpcRegistry, rpcBrokerPath);
routeChangeListener = new RoutedRpcListener(rpcRegistry, rpcBrokerPath);
rpcImplementation = new RemoteRpcImplementation(rpcBroker, schemaContext);
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;
}
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++;
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;
<module>toaster</module>
<module>toaster-consumer</module>
<module>toaster-provider</module>
+ <module>toaster-config</module>
<module>l2switch</module>
</modules>
<scm>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller.samples</groupId>
+ <artifactId>sal-samples</artifactId>
+ <version>1.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>toaster-config</artifactId>
+ <description>Configuration files for toaster</description>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/03-toaster-sample.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
<name>binding-data-broker</name>
</data-broker>
-
+
<notification-service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-notification-service
</notification-service>
</module>
</modules>
-
+
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<service>
<type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-subsystem</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </parent>
+ <artifactId>netconf-config</artifactId>
+ <description>Configuration files for netconf</description>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/01-netconf.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-subsystem</artifactId>
+ <version>0.2.5-SNAPSHOT</version>
+ </parent>
+ <artifactId>netconf-connector-config</artifactId>
+ <description>Configuration files for netconf-connector</description>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/99-netconf-connector.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<modules>
<module>netconf-api</module>
<module>netconf-cli</module>
+ <module>netconf-config</module>
<module>netconf-impl</module>
<module>config-netconf-connector</module>
<module>netconf-util</module>
<module>netconf-monitoring</module>
<module>ietf-netconf-monitoring</module>
<module>ietf-netconf-monitoring-extension</module>
+ <module>netconf-connector-config</module>
</modules>
<dependencies>