[SAGA-RG] Message API Evolution
Andre Merzky
andre at merzky.net
Mon May 10 13:03:50 CDT 2010
Dear Group,
the Messaging API originally evolved around a single endpoint class,
whose behaviour was, together with the endpoint's URL, determined by
a number of properties, all specified on creation time. In order to
satisfy the relatively wide range of use cases, the number of
properties was rather large, and included
- communication topology
- message reliability
- message delivery atomicity
- message correctness/completeness
- message ordering
(All properties can be left unspecified, and the URL schema can
pinpoint a specific protocol and transport medium to be used.)
Additionally, the API proposal contained a message class, which is
derived from saga::buffer, and allows to add application level
structure to that SAGA buffer. That message class also provides
some means of inspection (message origin and id, and generic user
level attributes MAY be available on the message instances).
There was some feedback (at OGF and on this list) that this API, and
in particular the endpoint class, may be cumbersome to use (too many
degrees of freedom), and that the ability to specify incompatible
endpoint properties (e.g. 'Unreliable & ExactlyOnce') was confusing.
There are, however, not many obvious ways how to remedy those points
without blowing the API out of proportion, or loosing coverage for
specific use cases. The examples attached to this mail illustrate
the different possible approaches: they contain the respective API
prototypes, and a short code example, which creates a visualization
pipeline segment (communicating a geometry between mapper and
renderer).
We are mentoring a google-summer-of-code student at LSU at the
moment (Hi Christos!), and his task is to provide a prototype
implementation of the message API. I would thus propose to have a
quick vote on one of the proposals below, to allow Christos to go
forward with the resulting option (remember: "rough consensus &
running code"). Once we have running code and a matching proposed
recommendation, we have two years time to gather experiences with
that, and should be prepared to switch to any of the other options
on the final recommendation, if needed.
So, please provide feedback to the following options, or provide
alternative options. FWIW, I also attach the current (generic) API
proposal again. Both the proposal and the code examples can be
found in svn, at
https://svn.cct.lsu.edu/repos/saga-ogf/trunk/documents/saga-package-messagebus
Thanks, and best regards, Andre.
(A) generic.cpp
The orginal API proposal, which described a single endpoint
class with multiple properties.
(B) specific.cpp
Specifying individual endpoint types for specific use case
classes makes those endpoints simpler (most properties are
preset), but also makes use case coverage difficult (one cannot
sensibly cover the complete property-space with individual
classes).
(C) topology.cpp
Specific individual endpoint classes for the different
communication topologies also blow the API, to some extent, but
also reduce the number of explicit endpoint properties (from 5
to 4). One could also consider to have different property
presets per topology class (like 'Unrealiable, Unordered' for
'PeerToPeer' endpoints, and 'Reliable, Ordered' for
'PointToPoint' endpoints), but that may be confusing to the
unaware end user.
(D) mixed.cpp
Another possible approach is to mix elements from the approaches
above: the API could include a generic_endpoint class, but also
topology specific endpoints, and/or use case class specific
endpoints. That may address all levels of end users, but would
also convolute the API significantly.
--
Nothing is ever easy.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: saga_messages.pdf
Type: application/pdf
Size: 241512 bytes
Desc: not available
Url : http://www.ogf.org/pipermail/saga-rg/attachments/20100510/6f2fcbf9/attachment-0001.pdf
-------------- next part --------------
namespace saga
{
namespace messaging
{
enum state
{
Unknown = 0,
New = 1,
Open = 2,
Closed = 3,
Dropped = 4
};
enum topology
{
Any = 0,
PointToPoint = 1,
Multicast = 2,
PublishSubscribe = 3,
PeerToPeer = 4
};
enum reliability
{
Any = 0,
Unreliable = 1,
Consistent = 2,
SemiReliable = 2,
Reliable = 3
};
enum atomicity
{
Any = 0,
AtMostOnce = 1,
AtLeastOnce = 2,
ExactlyOnce = 3
};
enum correctness
{
Any = 0,
Verified = 1,
Unverified = 2,
Signed = 3,
Encrypted = 4
};
enum ordering
{
Any = 0,
Unordered = 1,
Ordered = 2,
GloballyOrdered = 3
};
class message : public saga::buffer
{
public:
message (void);
message (int size);
message (void * data);
message (saga::buffer buf,
int size = -1);
~message (void);
std::string get_sender (void);
std::string get_id (void);
};
class endpoint;
class endpoint : public saga::object
, public saga::async
, public saga::monitorable
{
public:
endpoint (void);
endpoint (saga::object & obj);
endpoint (saga::url url,
topology t,
reliability r,
atomicity a,
correctness c,
ordering o);
~endpoint (void);
// inspection
saga::url get_url (void);
std::list <saga::url>
get_receivers (void);
// management methods
void serve (int n_clients = -1);
endpoint serve_once (float timout = -1.0);
void connect (float timout = -1.0);
void disconnect (void);
// I/O methods
void send (message m,
saga::url client = "",
float timout = -1.0);
int test (saga::url client = "",
float timout = -1.0);
message receive (saga::url client = "",
float timout = -1.0)
};
}
}
//////////////////////////////////////////////////////////////////////
//
// application example
//
class geometry
{
// ...
};
class geometry_message : public saga::messaging::message
{
// define how the message is serialized into and deserialized from a message
// buffer
};
void mapper_to_renderer (geometry geom)
{
// The generic endpoint class has all properties defaulting to
// 'Any', so we need to specify the properties (unless we are
// happy with Any, which we aren't in this use case).
saga::messaging::endpoint ep ("geom://remote.host.net:1234/renderer/",
saga::messaging::PublishSubscriber, // Topology
saga::messaging::Reliable, // Reliability
saga::messaging::AtMostOnce, // Atomicity
saga::messaging::Verified, // Correctness
saga::messaging::Unordered // Ordering
);
geometry_message gm (geom);
ep.send (gm);
}
-------------- next part --------------
namespace saga
{
namespace messaging
{
enum state
{
Unknown = 0,
New = 1,
Open = 2,
Closed = 3,
Dropped = 4
};
enum topology
{
Any = 0,
PointToPoint = 1,
Multicast = 2,
PublishSubscribe = 3,
PeerToPeer = 4
};
enum reliability
{
Any = 0,
Unreliable = 1,
Consistent = 2,
SemiReliable = 2,
Reliable = 3
};
enum atomicity
{
Any = 0,
AtMostOnce = 1,
AtLeastOnce = 2,
ExactlyOnce = 3
};
enum correctness
{
Any = 0,
Verified = 1,
Unverified = 2,
Signed = 3,
Encrypted = 4
};
enum ordering
{
Any = 0,
Unordered = 1,
Ordered = 2,
GloballyOrdered = 3
};
class message : public saga::buffer
{
public:
message (void);
message (int size);
message (void * data);
message (saga::buffer buf,
int size = -1);
~message (void);
std::string get_sender (void);
std::string get_id (void);
};
class endpoint;
class endpoint : public saga::object
, public saga::async
, public saga::monitorable
{
public:
endpoint (void);
endpoint (saga::object & obj);
endpoint (saga::url url,
topology t,
reliability r,
atomicity a,
correctness c,
ordering o);
~endpoint (void);
// inspection
saga::url get_url (void);
std::list <saga::url>
get_receivers (void);
// management methods
void serve (int n_clients = -1);
endpoint serve_once (float timout = -1.0);
void connect (float timout = -1.0);
void disconnect (void);
// I/O methods
void send (message m,
saga::url client = "",
float timout = -1.0);
int test (saga::url client = "",
float timout = -1.0);
message receive (saga::url client = "",
float timout = -1.0)
};
class reliable_pubsub_endpoint ...
class unreliable_pubsub_endpoint ...
class reliable_atomic_point2point_endpoint ...
class reliable_atomic_point2point_endpoint ...
class unreliable_point2point_endpoint ...
...
class point2point_endpoint ...
class peer2peer_endpoint ...
class multicast_endpoint ...
}
}
//////////////////////////////////////////////////////////////////////
//
// application example
//
class geometry
{
// ...
};
class geometry_message : public saga::messaging::message
{
// define how the message is serialized into and deserialized from a message
// buffer
};
void mapper_to_renderer (geometry geom)
{
// there is no specific endpoing class which exactly
// poinpoints all ep properties, so we use the more generic
// pubsub endpoint (which has the correct topology), and
// specify the other properties (Atomicity is here the
// non-default 'AtMostOnce').
saga::messaging::pubsub_endpoint ep ("geom://remote.host.net:1234/renderer/",
saga::messaging::Reliable, // Reliability
saga::messaging::AtMostOnce, // Atomicity
saga::messaging::Verified, // Correctness
saga::messaging::Unordered // Ordering
);
geometry_message gm (geom);
ep.send (gm);
}
-------------- next part --------------
namespace saga
{
namespace messaging
{
enum state
{
Unknown = 0,
New = 1,
Open = 2,
Closed = 3,
Dropped = 4
};
class message : public saga::buffer
{
public:
message (void);
message (int size);
message (void * data);
message (saga::buffer buf,
int size = -1);
~message (void);
std::string get_sender (void);
std::string get_id (void);
};
class reliable_pubsub_endpoint : public saga::object
, public saga::async
, public saga::monitorable
{
// default properties for the reliable pubsub endpoint are:
// Topology : PublishSubscriber
// Reliability : Reliable,
// Atomicity : ExactlyOnce,
// Correctness : Verified,
// Ordering : Unordered
public:
reliable_pubsub_endpoint (void);
reliable_pubsub_endpoint (saga::object & obj);
~reliable_pubsub_endpoint (void);
// inspection
saga::url get_url (void);
std::list <saga::url>
get_receivers (void);
// management methods
void serve (int n_clients = -1);
reliable_pubsub_endpoint serve_once (float timout = -1.0);
void connect (float timout = -1.0);
void disconnect (void);
// I/O methods
void send (message m,
saga::url client = "",
float timout = -1.0);
int test (saga::url client = "",
float timout = -1.0);
message receive (saga::url client = "",
float timout = -1.0)
};
class unreliable_pubsub_endpoint ...
class reliable_atomic_point2point_endpoint ...
class reliable_atomic_point2point_endpoint ...
class unreliable_point2point_endpoint ...
...
}
}
//////////////////////////////////////////////////////////////////////
//
// application example
//
class geometry
{
// ...
};
class geometry_message : public saga::messaging::message
{
// define how the message is serialized into and deserialized from a message
// buffer
};
void mapper_to_renderer (geometry geom)
{
// Our set of specific endpoints does not offer any endpoint with the exact
// properties we want, so we uses the closest match, which is the reliable
// pubsub endpoint, which has Atomicity set to ExactlyOnce, instead of the
// AtMostOnce we actually want.
saga::messaging::reliable_pubsub_endpoint ep ("geom://remote.host.net:1234/renderer/");
geometry_message gm (geom);
ep.send (gm);
}
-------------- next part --------------
namespace saga
{
namespace messaging
{
enum state
{
Unknown = 0,
New = 1,
Open = 2,
Closed = 3,
Dropped = 4
};
enum reliability
{
Any = 0,
Unreliable = 1,
Consistent = 2,
SemiReliable = 2,
Reliable = 3
};
enum atomicity
{
Any = 0,
AtMostOnce = 1,
AtLeastOnce = 2,
ExactlyOnce = 3
};
enum correctness
{
Any = 0,
Verified = 1,
Unverified = 2,
Signed = 3,
Encrypted = 4
};
enum ordering
{
Any = 0,
Unordered = 1,
Ordered = 2,
GloballyOrdered = 3
};
class message : public saga::buffer
{
public:
message (void);
message (int size);
message (void * data);
message (saga::buffer buf,
int size = -1);
~message (void);
std::string get_sender (void);
std::string get_id (void);
};
class pubsub_endpoint : public saga::object
, public saga::async
, public saga::monitorable
{
// default properties for the pubsub endpoint are:
// Topology : PublishSubscriber
// Reliability : Reliable,
// Atomicity : ExactlyOnce,
// Correctness : Verified,
// Ordering : Unordered
public:
pub_sub_endpoint (void);
pub_sub_endpoint (saga::object & obj);
pub_sub_endpoint (saga::url url,
reliability r,
atomicity a,
correctness c,
ordering o);
~pub_sub_endpoint (void);
// inspection
saga::url get_url (void);
std::list <saga::url>
get_receivers (void);
// management methods
void serve (int n_clients = -1);
endpoint serve_once (float timout = -1.0);
void connect (float timout = -1.0);
void disconnect (void);
// I/O methods
void send (message m,
saga::url client = "",
float timout = -1.0);
int test (saga::url client = "",
float timout = -1.0);
message receive (saga::url client = "",
float timout = -1.0)
};
class point2point_endpoint ...
class peer2peer_endpoint ...
class multicast_endpoint ...
}
}
//////////////////////////////////////////////////////////////////////
//
// application example
//
class geometry
{
// ...
};
class geometry_message : public saga::messaging::message
{
// define how the message is serialized into and deserialized from a message
// buffer
};
void mapper_to_renderer (geometry geom)
{
// our topology specific endpoint needs slightly different default
// property settings, so we specify them (Atomicity is here the
// non-default 'AtMostOnce').
saga::messaging::pubsub_endpoint ep ("geom://remote.host.net:1234/renderer/",
saga::messaging::Reliable, // Reliability
saga::messaging::AtMostOnce, // Atomicity
saga::messaging::Verified, // Correctness
saga::messaging::Unordered // Ordering
);
geometry_message gm (geom);
ep.send (gm);
}
More information about the saga-rg
mailing list