This is a proposal for a general-purpose protocol for “reserving” resources, e.g. reserving unique access to a locomotive node or reserving unique access for memory-configuration protocol. It grew out of (and in some places is a cut&paste from) capability in the memory-configuration protocol.
Note that this has not been agreed to by the general OpenLCB group. It's just a proposal. Details will change.
The basic idea is to provide a test-and-set approach to reservation. It goes through datagrams (but could be modified to use message level, which might be a bood idea if the messages can be kept short enough).
Small nodes shouldn't need a lot of processing power, e.g. to compress or decompress data in real time. Memory usage should also be limited, but is a second priority.
Operations should be state-less and idempotent to simplify software at both ends.
Multiple independent reservation operations can proceed at the same time. Multiple devices should be able to make reservations on separate nodes at the same time. Multiple overlapping reservations of overlapping resources in the same node should be possible.
For efficiency, reservation operations should fit into a single-frame CAN datagram (or small).
The mechanism for indicating which resource is being reserved should be general, extensible, and distributed.
To have a general-purpose protocol for reserving things, you have to specify what those things are. They're accessed within a specific node via addressed messages, so NodeID doesn't have to be part of the resource identification. But you need to have several, so that a given node can be separately locked for e.g. memory-configuration protocol, and also 5 different times for the 5 locomotives it's controlling.
Small is good, so that small nodes can deal with reservations easier. One or two bytes would be ideal.
There needs to be a way to allocate it. Using e.g. the byte value of a datagram-protocol ID would be nice because it's unambiuguous, and already allocated. But it doesn't work for datagram protocols that provide more than one thing to lock, nor for stream-based or other non-datagram-based protocols.
A full unique-ID (6 bytes) is easy to allocate, and makes it easy to associate event IDs with various lock indications. But it's a lot of space.
Compromise on two bytes: The first is flags and expansion, the second is a datagram-protocol ID, stream-protocol ID, etc as indicated by the flags.
But that doesn't fit in a single-frame datagram, so fall back to one byte, allocated via a common spreadsheet, using datagram-protocol values when available.
Send the following datagrams to reserve, release, etc.
Name |
Datagram Protocol ID byte |
Resource Selection Byte |
Content |
---|---|---|---|
Lock/Reserve |
(TBD) |
|
NodeID |
Lock/Reserve Reply |
(TBD) |
|
NodeID |
The configuring node sends a Lock datagram with its NodeID. If no node has locked this node, indicated by zero content in the lock memory, the incoming NodeID is placed in the lock memory. If a node has locked this node, the non-zero NodeID in the lock memory is not changed. In either case, the content of the lock memory is returned in the reply. This acts as a test&set operation, and informs the requesting node whether it successfully reserved the node. To release the node, repeat the lock operation with a zero NodeID. The lock memory is set to zero when the node is reset.
If receiving node doesn't implement the particular resource, it should reply with an error instead of Lock/Reserve Reply. (Another reason to go with messages instead of datagrams, because Optional Interaction Rejected has better error code semantics)
This grew out of the datagram-based configuration protocol, but should probably be just made into two messages. That occupies the same space, and removes the need to acknowledge the datagrams. The messages are small and have immediate execution, so there's no problem with having them be messages.
To ease implementation, zero should not be a valid resource ID.
Reservation involves at least 3 nodes: the one with the resource being reserved, the one holding the reservation, and one or more others who'd like a reservation but can't get it right now.
The one holding the resource doesn't actually need to know about the resource ID, as the reservation status doesn't change its actions (it's a reservation, not a lock).
But the others have to agree on the value for the system to work.
That indicates you need either a set of well-known global IDs, or a way to ask about locally defined IDs.
The writeup above is mostly about former. IDs are well known and associated with a particular protocol: "reserve use of configuration protocol".
But you might want to have a more general mechanism that can reference e.g. 1-of-n objects in a node: "reserve use of 5th virtual thing"
That would require more protocol support, but certainly could be done. If you want that someday, this protocol should stay in datagrams to have expansion room.
This is SVN $Revision: 2215 $