Archive

Posts Tagged ‘nodes’

How to load a module to a connected node in Erlang

July 12, 2010 Leave a comment

If you are in Erlang, you should have used somehow one or more Erlang nodes, even running in different computers.

A couple of weeks ago I was running a test of mine with two interconnected nodes, when I step into a problem: I had a module in the directory where I started the first node, but I wanted to use it also in the other node.

I didn’t want to replicate the beam file, so I took a look at c module documentation, and there I found the solution. The c module enables users to enter the short form of some commonly used commands; these functions are intended for interactive use in the Erlang shell only therefore the module prefix may be omitted.

I strongly recommend you this module, in test cases it is very useful.

I will show you how I fixed my problem.

First thing, start two nodes in different directories, in one directory  put the beam file of your module.

erl -sname node1@localhost -setcookie cookie
1>ls().
....
....
module.beam
2>nl(module).
abcast

In the example above, we started the first node (the one in the same directory of  module.beam), then using the function ls() we listed all the files in the directory. Using the function nl(module) we loaded module on all connected nodes (note that there is also nc(module) which compiles and then loads the code for a file on all nodes.

Here we have the second node (remember to start it before using nl()!):

erl -sname node2@localhost -setcookie cookie
1>m().
Module      File
....           ....
module      yourpath
3>module:function().
output of the function

As you can see the function m() displays information about the loaded modules, including the files from which they have been loaded, in the list given as output from m() you should have also your module, and from now you can use it as a normal module.

How to create a Java “Erlang” node with JInterface!

January 7, 2010 Leave a comment

For some things (maybe) Erlang is not the best language. Sometimes you have to deal with databases, GUI and other things that can be treated better with Java or other languages. But I’m sure about one things: if you want to built a distributed, fault tolerant system, you have to use Erlang.

The question thus is the following: how can we make Erlang code interact with other languages?

Well, if you are familiar to Java you may want to use JInterface, a library provided in the Erlang standard installation (or at least it should) that provides you functionalities for dealing with Erlang. As the title of the post says, my goal today is to build a Java “Erlang” node and pass messagges from it to a standard Erlang node.

The first instruction provided by JInterface you must know for this is the following:

OtpNode myOtpNode = new OtpNode("server");

Basically it creates a new node with the standard cookie, but you may also set a different cookie for the node using: 

OtpNode myOtpNode = new OtpNode("server", "mycookie");

So far I have only created an object myOtpNode which represents a node running in the host where it is executed, to “spawn” a new process you have to create a mailbox, that is identified by a pid or a registered name.

You can do it easily in the following way:

OtpMbox myOtpMbox = myOtpNode.createMbox("counter");

As you can see a new mailbox was created with name counter, actually the creation and naming can be done separately in the following way:

OtpMbox myOtpMbox = myOtpNode.createMbox();
myOtpMbox.registerName("counter");

Now you can refer to this node by its name, or by its pid that can be retrieve using:

OtpErlangPid myOptErlangPid = myOtpMbox.self();

OtpMbox has two important methods: send and receive that implement the sending and receiving operation of an
Erlang mailbox:

myOtpMbox.send(myOtpErlangPid, myOtpErlangTuple);
OtpErlangObject myOtpErlangObject = myOtpMbox.receive();

JInterface provides many Erlang types to developers. These types are actually converted from normal Java types;
most widely used are:

OtpErlangPid, OtpErlangTuple, OtpErlangBoolean, OtpErlangString, OtpErlangAtom, OtpErlangFloat,
OtpErlangLong.

Now let’s create a new node with the JInterface that implements the counter server we have seen in some previous post:

import com.ericsson.otp.erlang.*;

public class CounterServer
{

	public static void main(String[] args) throws Exception

         {

	       OtpNode myNode = new OtpNode("server");

                OtpMbox myMbox = myNode.createMbox("counterserver");

                OtpErlangObject myObject;

                OtpErlangTuple myMsg;

                OtpErlangPid from;

                OtpErlangString command;

                Integer counter = 0;

	       OtpErlangAtom myAtom = new OtpErlangAtom("ok");

	       while(counter >= 0) try

                {

                        myObject = myMbox.receive();

                        myMsg = (OtpErlangTuple) myObject;

                        from = (OtpErlangPid) myMsg.elementAt(0);

                        command = (OtpErlangString) myMsg.elementAt(1);

                        // here you may want to check the value of command

                        OtpErlangObject[] reply = new OtpErlangObject[2];

                        reply[0] = myAtom;

                        reply[1] = new OtpErlangInt(counter);

                        OtpErlangTuple myTuple = new OtpErlangTuple(reply);

                        myMbox.send(from, myTuple);

                        counter++;

		} catch(OtpErlangExit e)

                  {

                        break;

                  }

        }

}

Now, let’s create an Erlang client that tries to connect to the Java node and get the state of the counter:

-module(client).

-export([count/0]).

count() ->

	{countserver, 'server@pegaso'} ! {self(), "count"},

	receive

		{ok, Counter} ->

			io:format("Counter is at value: ~p~n", [Counter])

	end.

JInterface is inside your Erlang distribution…so to compile the java code and execute it, you must pass the right path to the java compiler and virtual machine. You can find the path by typing code:get_path() in the Erlang shell, once you have it type (note that you must put your path):

pegaso:Desktop bellerofonte$ javac -classpath ".:/usr/local/lib/erlang/lib/jinterface-1.4.2/priv/OtpErlang.jar" \
CounterServer.java

Ok, now your code should be compiled, but it order to allow the nodes networking you must start a programm called epmd (first search if it is already running as I did in the following code):

pegaso:Desktop bellerofonte$ epmd&
pegaso:Desktop bellerofonte$ epmd: Tue Jan 5 17:43:01 2010: epmd running - daemon = 0

pegaso:Desktop bellerofonte$ ps ax | grep epmd

2996 s000 S 0:00.01 epmd

2998 s000 R+ 0:00.00 grep epmd

Now execute the Java code:

pegaso:Desktop bellerofonte$ java -classpath ".:/usr/local/lib/erlang/lib/jinterface-1.4.2/priv/OtpErlang.jar" \
CounterServer

You can search if there are some nodes running in your machine as follows:

pegaso:Desktop bellerofonte$ epmd -names
epmd: up and running on port 4369 with data:
name server at port 52436

Ok, since I just want to check whether the Java code (and messagge passing) is working or not I’m not going to use the Erlang module I wrote above, but I’m going to test the functionalities of the Java counter server from an Erlang shell:

pegaso:Desktop bellerofonte$ erl -sname client

Erlang (BEAM) emulator version 5.6.5 

Eshell V5.6.5 (abort with ^G)

(client@pegaso)1> net:ping('server@pegaso').
pong

(client@pegaso)2> flush().
Shell got {ok,0}
ok

(client@pegaso)3> {counterserver, 'server@pegaso'} ! {self(), "count"}.
{<0.37.0>,"count"}

(client@pegaso)4> flush(). 
Shell got {ok,1}
ok

(client@pegaso)5> {counterserver, 'server@pegaso'} ! {self(), "count"}.
{<0.37.0>,"count"}

(client@pegaso)6> flush().
Shell got {ok,2}
ok

Well, it seems working!
Stay tuned for more stuff!

Categories: English, Erlang, Java Tags: , ,
Follow

Get every new post delivered to your Inbox.

Join 25 other followers