Virtual Network Channel

There is another way we can realise the channel routing that we implemented with the channel selector in the previous section. We could implement a custom type of ChannelCore implementation, that takes care of the routing internally. Functionally, this is relatively equivalent, but saves us quite a few object creations (just think of all those channels and selector instances if we have 1000 vnodes or more). However, ChannelCore code is not quite trivial, as there can be concurrency issues, the discussion of which would burst the bounds of this tutorial. Luckily, there already is an implementation of exactly the type of byte[]Array[Byte] id switching network channel, that we want: The VirtualNetworkChannel.

Dependencies

In order to be able to use this special kind of channel, we need to replace our kompics-port-network dependency, with the following one:

sbt
libraryDependencies += "se.sics.kompics.basic" % "kompics-port-virtual-network" % "1.2.1"
Maven
<dependency>
  <groupId>se.sics.kompics.basic</groupId>
  <artifactId>kompics-port-virtual-network</artifactId>
  <version>1.2.1</version>
</dependency>
Gradle
dependencies {
  compile group: 'se.sics.kompics.basic', name: 'kompics-port-virtual-network', version: '1.2.1'
}

Using a VirtualNetworkChannel

Before we can actually use the new kind of channel, we must change TAddress to implement virtual.Address and THeader to implement virtual.Header, instead.

Additionally, we must modify our setup code in the PingerParent, such that it uses VirtualNetworkChannel instead of the IdChannelSelector, which we can delete now.

PingerParent

Java
package jexamples.virtualnetworking.pingpongvirtual;

import com.google.common.primitives.Ints;
import se.sics.kompics.Channel;
import se.sics.kompics.Component;
import se.sics.kompics.ComponentDefinition;
import se.sics.kompics.Init;
import se.sics.kompics.config.Config;
import se.sics.kompics.network.Network;
import se.sics.kompics.network.virtual.VirtualNetworkChannel;
import se.sics.kompics.network.netty.NettyInit;
import se.sics.kompics.network.netty.NettyNetwork;
import se.sics.kompics.timer.Timer;
import se.sics.kompics.timer.java.JavaTimer;

public class PingerParent extends ComponentDefinition {

  public PingerParent() {
    TAddress baseSelf = config().getValue("pingpong.pinger.addr", TAddress.class);

    Component timer = create(JavaTimer.class, Init.NONE);
    Component network = create(NettyNetwork.class, new NettyInit(baseSelf));

    VirtualNetworkChannel vnc =
        VirtualNetworkChannel.connect(network.getPositive(Network.class), this.proxy);

    int num = config().getValue("pingpong.pinger.num", Integer.class);
    for (int i = 0; i < num; i++) {
      byte[] id = Ints.toByteArray(i);
      Config.Builder cbuild = config().modify(this.id());
      cbuild.setValue("pingpong.pinger.addr", baseSelf.withVirtual(id));
      Component pinger = create(Pinger.class, Init.NONE, cbuild.finalise());

      connect(pinger.getNegative(Timer.class), timer.getPositive(Timer.class), Channel.TWO_WAY);

      vnc.addConnection(id, pinger.getNegative(Network.class));
    }
  }
}
Scala
class PingerParent extends ComponentDefinition {

  val baseSelf = cfg.getValue[TAddress]("pingpong.pinger.addr");

  val timer = create[JavaTimer];
  val network = create[NettyNetwork](new NettyInit(baseSelf));

  val vnc = VirtualNetworkChannel.connect(network.getPositive(classOf[Network]), this.proxy);

  val num = cfg.getValue[Int]("pingpong.pinger.num");
  for (i <- 0 until num) {
    val id = Ints.toByteArray(i);
    val cbuild = this.config().modify(this.id());
    cbuild.setValue("pingpong.pinger.addr", baseSelf.copy(id = Some(id)));
    val pinger = create[Pinger](Init.none[Pinger], cbuild.finalise());

    connect[Timer](timer -> pinger);

    vnc.addConnection(id, pinger.getNegative(classOf[Network]));
  }
}

Execution

That is all. Run and execute the example the same way as before.

The source code for this page can be found here.