NetPacket (NetP) version 2 readme file NetPacket is a cross-language, cross-platform wrapper around PVM for the purpose of transparently and easily sending data from one process to another. It should work in C++, Python, and Java, on Linux and Mac OS X. If it doesn't, tell me what's wrong so I can try to fix it (eepness@mit.edu). Instructions given make the following assumptions (adjust for your situation accordingly): Your shell is tcsh. Your OS is Linux. Your PVM is installed in /mas/cogmac/pvm3 (most normal linux installations put it in /usr/share/pvm3) (If you don't have pvm, go get it from http://www.csm.ornl.gov/pvm/pvm_home.html). You keep your working sources in ~/svn. Your java installation is in /opt/jdk. Also, you need swig to convert the API to Java and Python. Check www.swig.org. We use swig-1.3.21. Oh, and make sure you have "scons" installed. That's an alternative to the standard "make". It's pretty straightforward to get and can be found at www.scons.org if "which scons" says you haven't got it. Any environment settings mentioned here should be made in your .cshrc (or .bashrc or equivalent) if you want them to work for future logins. In all relevant cases I assume you want to append to environment variables, but if the given variable doesn't already exist, just set it instead of appending. i.e., "setenv PATH /usr/local/bin" instead of "setenv PATH ${PATH}:/usr/local/bin" ************************************************************************* Installation 1. Download the source (for people at the MIT Media Lab; if you're elsewhere, you'll hopefully have solved the downloading bit already.) % cd ~/svn % svn checkout file:///mas/cogmac/svn/trunk/pvm/netp2 2. Compile % cd netp2 % setenv PVM_ROOT /mas/cogmac/pvm3 ("setenv PVM_ROOT /usr/share/pvm3" for many linux distributions) % setenv PVM_ARCH LINUX ("setenv PVM_ARCH LINUXI386" for many linux distributions) % setenv PVM_RSH /usr/bin/ssh % setenv JAVA_HOME /opt/jdk % scons all (just "scons" if you wish to skip Java and Python installation -- don't set JAVA_HOME in that case.) 3. Start PVM (you can use a hostfile:) % cat > hostfile.txt host1.mit.edu lo=username1 host2.mit.edu lo=username2 host3.mit.edu % pvm hostfile.txt (or you can add hosts manually:) % pvm pvm> add host1.mit.edu pvm> add host2.mit.edu Either way, make sure the path to the "pvm" executable is in your PATH environment variable. Notice that with the hostfile, you can specify what username to login to each machine with. Notice also that each and every computer you add to your PVM list must also have PVM installed, must have "pvm" in the default PATH variable of that account, and must set PVM_RSH, PVM_ROOT, and PVM_ARCH appropriately as mentioned above. Whenever you get stuck setting up pvm, first verify that you can ssh to each machine. Run pvm manually on each machine to ensure that it runs, and then do a "halt" to bring pvm on that machine down. _All_ machines on your PVM network must be added from one single host, so make absolutely sure you're not already running the pvm daemon on any of your other machines already. If pvm is having trouble running on a single machine, do a "ps aux" and kill any pvm-related processes lying around, and then "rm /tmp/pvm*" to remove any temporary files. Then try to bring up pvm again. Sometimes you get a "host is loopback" error. This is (iirc) because the machine can't look up its own ip address because its /etc/hosts has its name listed as 127.0.0.1. Just take the machine's hostname entry out of /etc/hosts so PVM can look up the machine's actual ip, or else start your initial PVM daemon from another machine. Notice also that if you happen to close the pvm console from which you originally added all the machines (you can close the console with "quit"), re-running pvm to add more machines may result in password prompts showing up in weird places and non-attached consoles, meaning you'll never be able to type the password to complete the ssh tunnel. You're best off not closing your pvm console until you're ready to halt pvm. When you're done using pvm, "halt" at the pvm console will kill all connected pvm machines simultaneously. If you get sick of typing passwords for every added machine every time, look into using ssh-agent and ssh-add. Left as an exercise to the reader. 4. Set up for your preferred languages. Test that it's working. C++: % setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${HOME}/svn/pvm/netp2/lib/${PVM_ARCH} % cd tests % xterm -e ./recvtest % xterm -e ./sendtest Java: % setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${HOME}/svn/pvm/netp2/lib/${PVM_ARCH} % setenv CLASSPATH ${CLASSPATH}:${HOME}/svn/pvm/netp2/lib/${PVM_ARCH}/netp.jar % cd tests % xterm -e java RecvTest % xterm -e java SendTest Python: % setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${HOME}/svn/pvm/netp2/lib/${PVM_ARCH} % setenv PYTHONPATH ${PYTHONPATH}:${HOME}/svn/pvm/netp2/lib/${PVM_ARCH} % cd tests % xterm -e python sendtest.py % xterm -e python recvtest.py ************************************************************************ Usage The relevant header files are in netp2/include, and the relevant library files are in netp2/lib/${PVM_ARCH}. If you want, you can install these somewhere else, but I'm going to assume you can just reference libraries from where you just compiled them to. The basic premise: make a NetP object. If you pass a string to the constructor, it's a send packet, sending on that channel. If you don't, it's a receive packet, and you must call joinChannel() to subscribe it to channels you want it to receive on. On the send side, create the NetP object, put data into it, and then run send(). On the receive side, create the NetP object, subscribe it to channels, and then loop waiting for data to be received. All the receive functions return a string corresponding to the channel on which the data was received. nReceive() is a non-blocking receive, which returns an empty string if nothing has been received. bReceive() is a blocking receive, which waits until something has been received. tReceive() is a timed receive, which takes an argument in seconds for how long to wait to see if a packet comes in; it returns the empty string if nothing has been received in that amount of time. Similarly, nReceiveNewest(), bReceiveNewest(), and tReceiveNewest() work the same way, only they discard all older packets. peek() tells you if a packet is waiting to be received. Once a packet has been received, check which channel it came in on, and decide what to do with the included data. Examples follow... ------------------------------------------------------ - C++ (For environment settings see the last part of the "compile" section) -- Compile options: g++ -o myprogram myprogram.cpp -I ${HOME}/svn/pvm/netp2/include -L ${HOME}/svn/pvm/netp2/lib/${PVM_ARCH} -lnetp -- send code: #include "NetP.h" int main() { NetP sendp("MyChannel"); // channel argument means it's a send instance sendp.data() = 1; // data() is a PData; more details later sendp.send(); sendp.data().eval("[1, 2, 3, 4, 5]"); // make a list PData sendp.send(); } -- simplest receive code: #include "NetP.h" int main() { NetP recvp; // no argument means it's a receive instance recvp.joinChannel("MyChannel"); string resp = recvp.bReceive(); // blocking receive cout << recvp << endl; } -- typical receive code: #include "NetP.h" int main() { NetP recvp; // no argument means it's a receive instance recvp.joinChannel("MyChannel"); while (1) { // loop forever string resp = recvp.bReceive(); // blocking receive if (resp == "MyChannel") { // receive instances can get many channels, so check which channel if (recvp.data().getType() == "int") { // check type of PData int result = (int)recvp.data(); // PData's can print directly, or be cast to primitive types cout << "int: " << result << endl; } else if (recvp.data().getType() == "list") { for (int i=0; i