This page describes a semi-(mostly??)-obsolete technique to access the contents of the atomspace. There are multiple problems with this system: foremost, it was painfully slow: real-life data processing requires churning through hundreds of thousands of atoms per second, tweaking assorted values on each; the ZeroMQ/RESTful interfaces run at least two orders of magnitude slower, and are thus impractical, except for casual browsing.
- Install zeroMQ (should already be installed); for eclipse: add zmq to libraries
- Install protocol buffers (should already be installed)
./configure make sudo make install
eclipse: add protobuf to libraries
Compile proto file (if changed)
protoc --cpp_out=. AtomSpaceMessages.proto
How to compile
- Add new files and libs to
ZMQMessages.pb.cc, ZMQServer.cc, ZMQClient.cc, ProtocolBufferSerializer.ccto
ADD_LIBRARY (atomspace SHARED
protobuf to <code>SET(ATOMSPACE_LINK_LIBS
ZMQMessages.pb.h, ZMQServer.h, ZMQClient.h, ProtocolBufferSerializer.hto
flags.makefile in the following folders:
How to use
- Link with AtomSpace
- Create a
ZMQClientinstance and call its methods
ZMQClient* zmqClient = new ZMQClient(); //defaults to localhost zmqClient->getAtom(h);
If the cogserver is running on a different PC
ZMQClient* zmqClient = new ZMQClient("tcp://126.96.36.199:5555");
How it works
ZeroMQ allows you to connect a client process to the atomspace managed by the server (normally the cogserver). Use cases include deploying an agent on a separate server, easier debugging of agents, connecting components that are written in different languages (any language that supports protocol buffers can use a simple message based wrapper to talk to the server. Of course implementing the full atomspace OO interface takes a lot more work. ) and connecting tools that need high performance access to the atomspace (e.g. the atomspace visualizer). You can connect multiple clients to one server. The clients can be anywhere in the world as long as the server is reachable via TCP/IP.
Message Exchange Pattern
Currently we use a simple request-reply pattern using socket types
REQ for client and
REP for server.
- Simple to implement for straightforward use cases.
- Blocks for each request (both client and server)
- We can use multiple sockets in multiple threads but this requires thread management and socket management. It's probably better to use a different socket type for extended request-reply pattern anyway.
TODO: Consider DEALER/ROUTER socket types.
Now we can switch out both REQ and REP with DEALER and ROUTER to get the most powerful socket combination, which is DEALER talking to ROUTER. It gives us asynchronous clients talking to asynchronous servers, where both sides have full control over the message formats.
if server is enabled run zmqloop zmqloop check for RequestMessage switch(function) case getAtom: call getAtom with arguments from RequestMessage store return value in ReplyMessage case getName: etc... send ReplyMessage
async queue works the same as usual but if client is enabled call server instead of Run copy ASRequest arguments and function number to RequestMessage send RequestMessage to server wait for ReplyMessage copy ReplyMessage to ASRequest
Neo4j Graph Backing Store
ZeroMQ and the protobuf serialization is used to communicate with Neo4j Backing Store (currently work in progress).
It doesn't matter if you start the server or client first but if the server crashes or is restarted you have to restart the client(s) as well. If you get error "Address already in use" then another instance of the server is already running
- febcorpus.scm doesn't load
- clean exit of atomspaceasync without using sleep or a busy loop
send ctrl+C signal to the thread and break when NULL message received char *reply = zstr_recv (client); if (!reply) if(exitSeverloop) logger.info "Serverloop exitting" break; else logger.error "Serverloop quit unexpectedly"
- what if dowork throws an exception on the server? catch exceptions, put them in reply message and rethrow at client
- try to handle communications exceptions locally