Communicating with components from non Axon code
The Handle component wraps another component and allows data to be sent to and received from its standard inboxes ("inbox" and "control") and standard outboxes ("outbox" and "signal"). It provides this via thread safe, non-blocking get() and put() methods.
This is particularly useful in combination with Axon.background - allowing communication with components running in the background of a non Axon based piece of code.
This code is currently experimental - we'd welcome reports of any issues you may encounter when using this code.
Here, Axon/Kamaelia is used to connect to a server then receive text, chunking it into individual lines. This is done by using Axon in the background (since other code in this hypothetical system is not Axon based).
We can now fetch items of data when they arrive, using the Handle, from the "outbox" outbox of the pipeline:
from Queue import Empty while 1: try: received_line = connection.get("outbox") print "Received line:", received_line except Empty: # no data yet time.sleep(0.1)
We can also send data, back to the server, by sending it to the "inbox" inbox of the pipeline:
connection.put("Bytes to send to server\n", "inbox")
Handle is a threaded component. It does not have the standard inboxes ("inbox" and "control") or standard outboxes ("outbox" and "signal"). The only way to communicate with Handle is via its get() and put() methods.
Instantiate Handle, passing it a component to wrap. Upon activation, Handle automatically wires inboxes and outboxes of its own to the "inbox" and "control" inboxes and "outbox" and "signal" outboxes of the component it is wrapping. Handle then activates the wrapped component.
To send data to the wrapped component's "inbox" or "control" inboxes, call the put() method, specifying, as arguments, the item of data and the name of the inbox it is destined for. The data is queued and sent at the next opportunity.
To retrieve data sent out by the wrapped component's "outbox" or "signal" outboxes, call the get() method, specifying, as an argument, the name of the outbox in question. This method is non blocking - if there is data waiting, then the oldest item of data is returned, otherwise a Queue.Empty exception is immediately thrown.
When the wrapped component terminates, Handle will immediately terminate. Handle does not respond to shutdown messages received from the wrapped component. Handle cannot be sent shutdown messages since it has no "control" inbox on which to receive them.
Handle currently only provides access to the standard "inbox" and "control" inboxes and standard "outbox" and "signal" outboxes of the component it wraps.
If access is required to a different inbox or outbox, try wrapping the component within a Kamaelia.Chassis.Graphline component and specifying linkages to connect the inbox or outbox in question to one of the standard inboxes or outboxes of the Graphline.
The current implememntation of Handle involves a degree of polling. However it does use a slight (approximately 1 centisecond) delay between pollings.
Therefore when idle, CPU usage of this component will be slightly greater than zero.
This component is the successor to the earlier "likefile" component. Likefile suffered from some design issues that resulted in occassional race conditions.
We dropped the name "LikeFile" since whilst it derives from the concept of a file handle, it doesn't use the same API as file() for some good reasons we'll come back to.
A file handle is an opaque thing that you can .write() data to, and .read() data from. This is a very simple concept and belies a huge amount of parallel activity happening concurrently to your application. The file system is taking your data and typically buffering it into blocks. Those blocks then may need padding, and depending on the file system, may actually be written immediately to the end of a cyclone buffer in a journal with some write operations. Then periodically those buffers get flushed to the actual disk.
Based on the fact that file handles are a very natural thing for people to work with, based on their ubiquity, and the fact that it masks the fact you're accessing a concurrent system from a linear one, that's why we've taken this approach for integrating Kamaelia components (which are naturally parallel) with non-Kamaelia code, which is typically not parallel.
For simplicity of implementation, initially the implementation of Handle supports only the equivalent of non-blocking file handles. This has two implications:
Methods defined here
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
Unplugs any children that have terminated, and returns true if there are no running child components left (ie. their microproceses have finished)
Return an item of data sent to an outbox of the wrapped component.
This method is non blocking and always returns immediately. If there is no data to return, then the exception Queue.Empty is thrown
Send an item of data to one of the inboxes of the wrapped component.
The item of data is queued and sent to the inbox as soon as possible.
Methods inherited from Axon.ThreadedComponent.threadedcomponent :
Methods inherited from Axon.Component.component :
Got a problem with the documentation? Something unclear that could be clearer? Want to help improve it? Constructive criticism is very welcome - especially if you can suggest a better rewording!
Please leave you feedback here in reply to the documentation thread in the Kamaelia blog.
-- Automatic documentation generator, 01 Feb 2010 at 04:00:28 UTC/GMT
This is an ongoing community based development site. As a result the contents of this page is the opinions of the contributors of the pages involved not the organisations involved. Specificially, this page may contain personal views which are not the views of the BBC. (the site is powered by a wiki engine)
(C) Copyright 2008 Kamaelia Contributors, including the British Broadcasting Corporation, All Rights Reserved