TomP2P and SimGrid

TomP2P offers an integration to simulate P2P networks using the SimGrid platform. According to the project site, "SimGrid is a toolkit that provides core functionalities for the simulation of distributed applications in heterogeneous distributed environments. The specific goal of the project is to facilitate research in the area of parallel and distributed large scale systems, such as Grids, P2P systems and clouds. Its use cases encompass heuristic evaluation, application prototyping or even real application development and tuning."

The TomP2P-SimGrid integration provides the interface net.tomp2p.simgrid.Simulation to the user. With this interface and the platform and deployment XML files, a simulation of a P2P network can be created. The platform XML files specifes how the network looks like, while the deployment XML file specifies the peers. The rest is taken care of by the interface library TomP2P-SimGrid.

The following examples show how to use TomP2P with SimGrid. Please note that it currently works out of the box only with 64bit Linux, since I have not cross compiled the native libraries for the other platforms and bundled it with TomP2P-SimGrid. If you have libraries for the other platforms, please let me know (tom-at-tomp2p.net).

The examples with all the dependencies can be downloaded. For a quickstart, download the Eclipse project. Make sure you have m2e installed. The source can be found on GitHub.

Hello World Example

The Hello World example starts 1000 peers and each of the peer prints its name and quits. There are no communication meessages send around in this example.

public class HelloWorld implements Simulation
{
	public static void main(String[] args) throws IOException
	{
		//set the callback
		SimGridTomP2P.setSimulation(new HelloWorld());
		//start SimGrid
		SimGridTomP2P.main(args);
	}
	@Override
	public void simulate(Peer peer, Process process, String[] args) throws Exception
	{
		Msg.info("Hello world, I'm peer "+peer.getPeerID());
	}
}

To start it, download the examples with all the dependencies, unzip it and execute java -cp TomP2P-SimGrid-Example-1.0.1-SNAPSHOT.jar net.tomp2p.simgrid.example.HelloWorld platforms/one_cluster_1000_hosts.xml deployments/deployment-1000.xml. The output should look like:

[0.000000] [jmsg/INFO] peers created
[0.000000] [jmsg/INFO] Ready to run MSG_MAIN
[0:net.tomp2p.simgrid.SimulationLoop:(1) 0.000000] [jmsg/INFO] Hello world, I'm peer 0xb6589fc6ab0dc82cf12099d1c2d40ab994e8410c
[1:net.tomp2p.simgrid.SimulationLoop:(4) 0.000000] [jmsg/INFO] Hello world, I'm peer 0x356a192b7913b04c54574d18c28d46e6395428ab
[2:net.tomp2p.simgrid.SimulationLoop:(7) 0.000000] [jmsg/INFO] Hello world, I'm peer 0xda4b9237bacccdf19c0760cab7aec4a8359010b0
...

Put / Get Example

This example bootstraps all peers and as soon as a peer bootstraps it either stores data in the DHT or fetches the data from the DHT.

public class BoostrapPutGet implements Simulation
{
	public static void main(String[] args) throws IOException
	{
		//set the callback
		SimGridTomP2P.setSimulation(new BoostrapPutGet());
		//start SimGrid
		SimGridTomP2P.main(args);
	}

	@Override
	public void simulate(Peer peer, Process process, String[] args) throws Exception
	{
		Number160 bootstrapTo = Number160.createHash(args[0]);
		PeerAddress bootstrapPeer = new PeerAddress(bootstrapTo);
		bootstrap(peer.getPeerID(), bootstrapTo, peer, bootstrapPeer);
	}
	
	private void doDHT(Peer peer) throws IOException
	{
		if(peer.getPeerID().hashCode() % 5 == 0)
		{
			FutureDHT futureDHT = peer.put(Number160.createHash("storeme"), new Data(new String("I stored my host name "+peer.getPeerID())));
			futureDHT.addListener(new BaseFutureAdapter<FutureDHT>()
			{
				@Override
				public void operationComplete(FutureDHT future) throws Exception
				{
					System.out.println("put "+future.isSuccess());
				}
			});
		}
		else
		{
			FutureDHT futureDHT = peer.get(Number160.createHash("storeme"));
			futureDHT.addListener(new BaseFutureAdapter<FutureDHT>()
			{
				@Override
				public void operationComplete(FutureDHT future) throws Exception
				{
					System.out.println("get "+future.isSuccess());
				}
			});
		}
	}
	
	private void bootstrap(Number160 peerID,Number160 bootstrapTo, final Peer peer, PeerAddress bootstrapPeer)
	{
		if(!peerID.equals(bootstrapTo))
		{
			System.out.println("bootstrap from " + peerID + " to " + bootstrapTo);
			peer.bootstrap(bootstrapPeer).addListener(new BaseFutureAdapter<FutureBootstrap>()
			{
				@Override
				public void operationComplete(FutureBootstrap future) throws Exception
				{
					System.out.println("bootstrap success " + future.isSuccess());
					doDHT(peer);
				}
			});
		}
	}
}

To start it, download the examples with all the dependencies, unzip it and execute java -jar TomP2P-SimGrid-Example-1.0.1-SNAPSHOT.jar platforms/one_cluster_1000_hosts.xml deployments/deployment-1000.xml. The standard output should look like:

put true
bootstrap success true
bootstrap success true
get true
bootstrap success true
bootstrap success true
get true
get true
bootstrap success true
get false

The last line shows get false, that indicates the data was not found on the DHT. In this scenario, this is correct, since we have a lot of churn and we may query those fresh peers that do not have the data stored yet.

Limits and Other Issues

Since this is work in progress, there are some unresolved issues, which we are working on.

Standard Output / Error Output

Currently, the messages sent around are printed to standard error and look like:

[10:net.tomp2p.simgrid.TomP2PSender:(33) 0.010408] [jmsg/INFO] Message sent Message:id=-1940422356,c=NEIGHBORS_STORAGE,t=REQUEST_2,l=56, s=PeerAddr[/192.168.2.4,udp:7700,tcp:7700,ID:0xb1d5781111d84f7b3fe45a0852e59758cd7a87e5], r=PeerAddr[null,udp:-1,tcp:-1,ID:0xb6589fc6ab0dc82cf12099d1c2d40ab994e8410c]
[0:net.tomp2p.simgrid.TomP2PReceiver:(2) 0.010408] [jmsg/INFO] Message received and added to reply queue Message:id=-1940422356,c=NEIGHBORS_STORAGE,t=REQUEST_2,l=56, s=PeerAddr[/192.168.2.4,udp:7700,tcp:7700,ID:0xb1d5781111d84f7b3fe45a0852e59758cd7a87e5], r=PeerAddr[null,udp:-1,tcp:-1,ID:0xb6589fc6ab0dc82cf12099d1c2d40ab994e8410c]

This means that for evaluating your network, you have to write a parser. Please note that the format can change with new versions of TomP2P-SimGrid. In the second example, I’m using the standard output to see what is going on in the network. The difference between standard output and error output is that standart output may be buffered, while the error output is shown immediately.

Memory Limit

I could run up to 7500 peers on my laptop and it seems that the limit is the memory, since with more peers, I’m getting: Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread. I used the following parameters java -Xmx1000m -Xss256k -jar TomP2P-SimGrid-Example-1.0.1-SNAPSHOT.jar platforms/one_cluster_7500_hosts.xml deployments/deployment-7500.xml. To increase this size, read here how to tune the parameters. The parameters that worked for us are:

Native Libraries

The native libraries libsimgrid.so and libSG_java.so are bundled in TomP2P-SimGrid-1.x.y.jar. However, since I have not cross-compiled SimGrid and the Java bindings, I only can provide Linux-x64 libraries at the moment. If you have an other platform, please go to the SimGrid website, download SimGrid and the Java binding and compile it. Alternatively, instead of compiling SimGrid you can download a binary packet and install it with apt-get or similar. Just make sure you have the version 3.6.2. You can then either copy the libraries into the jar file (TomP2P-SimGrid-1.x.y.jar), copy the libraries to a system folder, or set the library path accordingly (-Djava.library.path=yourpath). If you have the navtive libraries for example in /tmp, you should run the application as follows: java -Djava.library.path=/tmp -jar TomP2P-SimGrid-Example-1.0.1-SNAPSHOT.jar platforms/one_cluster_1000_hosts.xml deployments/deployment-1000.xml

Future.await and Future.awaitUninterruptibly

Regular blocking operations are a no-go in TomP2P-SimGrid. Since I have not changed the Future classes, you cannot use Future.await and Future.awaitUninterruptibly because it will deadlock. A fix would be to use the wait(), notify(), sleep() provided in the SimGridTomP2P and Timings classes. However, since rock-star software engineers do not need blocking operations, you won’t run into any issues :)