Message-passing with Plasma
The Plasma message-passing system makes it painless to communicate within a program, between different programs, or between different machines in a network.
Plasma messages are called proteins. They’re sent according to a simple variation on publish-subscribe.
In brief, to send a message, one party puts it in an intermediate container called a pool. Any number of other clients can listen for the messages that arrive in a pool (we call this “metabolizing” a protein). And everybody can put messages into a pool (we call this “depositing”).
We refer to plasma messages as proteins. Each protein has two parts: descrips and ingests. The descrips is a header (we call it ‘descrips’ because there are description strings in it). The ingests section contains the message payload. It’s just a map of key/value pairs.
Values can be any of a variety of data units: 64-bit integers, 64-bit floats, booleans, strings, lists, maps, raw bytes, other entire proteins, etc. The ingests map is highly flexible; it’s similar to a JSON map, but it understands more types.
Pools are a transport and storage mechanism for proteins. Pools are simply an ordered list of proteins. New proteins always append to the end.
Pools are a ring buffer; when they reach their maximum size, they wrap around to the beginning and start overwriting the oldest proteins.
Greenhouse objects can put proteins into pools whenever they like; they can also sign up to listen for new proteins that appear in the pool. We call this “participating in” a pool. Essentially, it’s a publish/subscribe model. When a new protein goes into a pool, all participants “metabolize” that protein immediately.
At a basic level, a pool is just a file on disk, which is managed in a well-defined way by the Greenhouse Plasma libraries. Since other Greenhouse applications can safely access the same pool, pools are an extremely robust mechanism for inter-process communication.
But pools can also be advertised and accessed over a network. The programs ‘pool-tcp-server’ and ‘pool-server-zeroconf-adapter’ run in the background and do this task. pool-tcp-server makes all the machine’s pools accessible on port 65456. These programs are installed as system services by the Greenhouse installer.
Local pools can be referred simply by their unqualified name (‘foo’). Remote pools (served by pool-tcp-server) can be referred to with the ‘tcp://hostname/poolname’ format.
There is a set of command line tools that can be used to use and test pools (see examples).
Because proteins are stored according to the time they’re deposited, not only are they useful for communication, but they also can provide a kind of history for an application.
What facilities are there for working with pools?
There is a collection of command line utilities. Firstly, peek and poke are very flexible and mature tools for getting proteins in and out of pools. See peek –help and poke –help
The collection of tools starting with “p-“ (p-await, p-list, p-create, p-stop) are simpler, single-purpose tools.
For programming, Greenhouse ships with Plasma bindings for C++ and Ruby.
What are pools, actually?
A pool is a binary file that lives in the directory /var/ob/pools
What does it mean to “stop” a pool?
It means to delete the pool’s directory (/var/ob/pools/foo/) and all its files from disk – they’re gone. (It’s been noted that the utility p-stop could be helpfully renamed to p-erase or p-delete.)
What is pool-tcp-server?
Also known as a “pool server”, pool-tcp-server has a single purpose: it exposes a collection of pools on a TCP port. At that point, all these pools become completely public.
The address of pools published in this fashion is tcp://machine-name/pool-name. “foo” becomes available as “tcp://localhost/foo” – but plain old “foo” still works, for local access. Outsiders must access it as “tcp://machine-name/foo”.
The default pool-tcp-server port is 65456. (Note: counts down from 6 to 4, and then back up again.)
Another useful tidbit: to run pool-tcp-server in the foreground, instead of forking it off as a daemon and possibly losing track of it, use the -n option.
Multiple different pool-tcp-servers can be run at once, but each one must use its own port; they can’t share a port.
What is the functional difference between accessing pool “foo” and “tcp://localhost/foo”?
As long as pool-tcp-server is actually running, there’s not much difference. The former is probably a bit faster.
Can I move pool data from one machine to another?
Yes; pools are just files. They can be copied, moved around, backed up, zipped and emailed, etc. They aren’t magic.
There are ways to slurp directly from one pool to another, for example by using peek and poke in tandem. The following command will copy the most recent protein from pool ‘foo’ (on machine-a), and deposit it to pool ‘bar’ (on machine-b).
peek -1 tcp://machine-a/foo | poke tcp://machine-b/bar
At Oblong we call these kinds of things Stupid Poke Tricks, and they are awesome.
//in the terminal //to create a pool called 'book': $ p-create book //To know the pool size and status: $ p-info book //To list all the local pools: $ p-list //To look at what is going on in a pool (very useful to test your code): $ peek book //To destroy a pool: $ p-stop book