Programming with libsockhop.so (the SockHop shared library)

Overview
Virtual network architecture
Format of a typical SockHop program
Example program source
Compiling SockHop programs
Writing your own SHWorker subclasses
Writing your own SHSorter subclasses
 


Overview:  The environment under SockHop

SockHop is a software kit designed to allow BeOS programs to run easily on many (many!) machines at once.  It is designed mainly for controlled environments where the programmer has access to and control over one or more BeOS machines, and knows in advance which machines will be used to run the parallel program.  Using SockHop, the programmer can write a program on a single BeOS machine, but test and run it on every machine in the lab, without ever needing to leave his or her chair.  SockHop handles all the network communication, message routing, code propagation, and so on, leaving the programmer free to concentrate on the actual application.
 


SockHop's Virtual Network Architecture

In a SockHop program, the "SockHop Virtual Machine" takes the form of a tree of nodes.  For many applications, the tree need not be more than one or two levels deep, but theoretically the tree could grow to any size or depth.

Here are some important qualities of the tree:


 

Format of a typical SockHop program.

A typical SockHop program will do the following things:

  1. Create or designate a BLooper that SockHop will send its reply BMessages to.
  2. Create the root node of a virtual network by calling SHCreateRootNode().
  3. Post BMessages to the root node telling it to create some child nodes (and possibly after that post messages to some of the child nodes telling them to create grandchild nodes, and so on)
  4. Instantiate some objects of one or more SHWorkers subclasses, Archive() them, and send them to various nodes.
  5. Post BMessages to control the behavior of the SHWorkers, and receive BMessages from the SHWorkers that indicate the results.
  6. When all is done, call Lock() and Quit() on the root node (since the root node is a BLooper), and exit. Destroying the root node will cause the rest of the tree to disappear as well.
 


A simple example

Here is an example of a simple, do-almost-nothing SockHop program.  It assumes the following conditions are true:

  1. There exist computers named beos1.sockhop.com, beos2.sockhop.com, and beos3.sockhop.com, on the network, and that they are all running BeOS, and that they all have a SockHop server running on port 2958 (the default SockHop port)
  2. An add-on file containing an SHWorker subclass named SHTestWorker has been placed in the correct location(s) relative to this program's current directory (the actual place it needs to be is up to the add-on code, but is often something like "./add-ons/x86/SHTestWorker" for the Intel flavor, and "./add-ons/ppc/SHTestWorker" for the PowerPC flavor)
  3. This program needs to link against the SHTestWorker add-on, in order to construct an SHTestWorker object to Archive() and send.  Thus, the SHTestWorker add-on must be in a directory specified by the LIBRARY_PATH variable (otherwise, this program won't execute at all!)
/*----------- begin sample code ----------- */

#include <sockhop/SockHop.h>
#include "SHTestWorker.h"

// We need a BLooper to receive the BMessages that SockHop
// sends back to us.  This one will just print out any
// BMessage it receives.
class DebugLooper : public BLooper
{
private:
  virtual void MessageReceived(BMessage * msg)
  {
     printf("DebugLooper:  Received this message from SockHop:\n");
     msg->PrintToStream();
  }
};

int main(int argc, char ** argv)
{
   // Create a target BLooper to receive reply BMessages
   DebugLooper * debugLooper = new DebugLooper;
   debugLooper->Run();

   // Create the root node ("/") of the SockHop tree
   BLooper * root = SHCreateRootNode(BMessenger(debugLooper));
   if (root == NULL)
   {
      printf("Error, couldn't create root node!\n");
      exit(5);
   }
   root->Run();

   // Tell the root node to add our three computers as children.
   BMessage createKids(SH_COMMAND_ADDCOMPONENTS);
   createKids.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("node-A", "beos1.sockhop.com"));
   createKids.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("node-B", "beos2.sockhop.com"));
   createKids.AddFlat(SH_NAME_CHILDREN, &SHNodeSpec("node-C", "beos3.sockhop.com"));
   createKids.AddString(SH_NAME_TO, "/");
   root->PostMessage(&createKids);

   // Create an SHTestWorker, and then capture its essence into a BMessage.
   // SHWorkers (and hence SHTestWorkers), unlike real BLooper subclasses, can be
   // safely created on the stack.
   SHTestWorker testWorker("I'm a test worker!");
   BMessage testWorkerMsg;
   testWorker.Archive(&testWorkerMsg);

   // Now send a copy of the SHTestWorker to all three child nodes.
   // Note how wildcarding is used to specify all three children's
   // node paths ("/node-A", "/node-B", and "/node-C") at once.
   BMessage sendWorker(SH_COMMAND_ADDCOMPONENTS);
   sendWorker.AddMessage(SH_NAME_COMPONENTS, &sendWorker);
   sendWorker.AddString(SH_NAME_TO, "/node-*");
   root->PostMessage(&sendWorker);

   // Now we will send a BMessage to the SHTestWorkers, just
   // for fun.  How they interpret it is up to them.
   BMessage msg('helo');
   msg.AddString(SH_NAME_TO, "/node-*");
   root->PostMessage(&sendWorker);

   // Lastly, we shut down our root node and debugLooper.
   // Note that shutting down the root node will cause
   // the three remote nodes to automatically shut down as well.
   if (root->Lock()) root->Quit();
   if (debugLooper->Lock()) debugLooper->Quit();

   return 0;
}

/* --------- end sample code ------------ */

 

Tips for compiling SockHop programs

When compiling SockHop programs, here are some useful facts to keep in mind:


 

Writing your own SHWorker subclasses

Writing SHWorker subclasses is something every SockHop programmer has to do in order to create code that can be automatically propagated to multiple machines.  Fortunately, SHWorkers are very similar in concept to BLoopers, so you probably already mostly know how they work.  The rest of what you need to do to implement an SHWorker can be found by reading the SHWorker class documentation, and by remembering the tips below:


 

Writing your own SHSorter subclasses

Writing an SHSorter subclass is something that most SockHop programs won't need to do--IMHO, the included SHWi1dPathSorter class will be sufficient for 99% of the apps that might be written for SockHop.  However, custom message routing can be handy sometimes, so SockHop lets you write your own BMessage routing algorithms by creating SHSorter subclasses and distributing your own custom SHSorter objects to the nodes in your tree.  To find out more about how to do this, read the SHSorter class documentation, and remember the following tips: