The _state module is a protocol extension of PSYC. It employs modifiers in the PSYC syntax and allows variables to be stored permanently and optionally be modified by little changes without retransmitting them each time.
This concept hasn't actually been put to use in psyced but it is fundamental for the modeling of the social graph and many other functions in secushare, that's why this is mostly relevant for PSYC2.
State not only is a protocol optimization of PSYC in terms of bandwidth, it also provides for remote data to be available locally and under normal circumstances up to date with the sender. This avoids unnecessary query/retrieval operations in particular in the area of presence and profiles, especially when multicast is in the game.
A practical example: With decentralized state you can show a photo of each person in your buddy list and be sure that it is not last week's cached copy. You subscribe to that person's state, and changes are pushed to you. Of course you can do this in XML or by the use of custom PSYC methods, but the state modifier syntax provides for a generic, unified and obvious interface to achieve any of this kind of jobs. You can think of a thousand similar applications. The advantage of push versus poll or discovery in this case is the synchronicity in it: You can just go ahead and use the data, you don't have to postpone it until some network traffic has confirmed, that the stuff is up to date.
Still, for some applications statelessness is very valuable, so PSYC can also be employed in a stateless way.
The term state comes from computer science, and maybe it's easier to think of it as the opposite of being stateless. In PSYC we speak of state as soon as we employ persistent variables. Forget about automata theory. ;)
Within PSYC's routing layer, the scope of persistent variables is merely the circuit being used, in the direction of the sender to the recipient. This is easy to handle.
In the end-to-end part of the PSYC packet, persistent variables are defined within a channel from the sending context to the receiving entities. This makes end-to-end state quite powerful, but also a hassle to implement. That's why we have obsoleted unicast end-to-end state and limited ourselves to only do multicast context state. psyced still doesn't provide either of these, thus it never sends stateful packets.
Global shared state
RFC 1324 states:
The potential userbase of a conferencing system using the internet should not be underestimated. It is therefore desirable that the conferencing system should be as distributed as possible, and as little state information kept as possible.
Such global shared state is the eminent scalability problem in the design of the IRC protocol, which both PSYC and XMPP have overcome. The main problem with IRC's global state is: as soon as a link goes down, all the state data is no longer of any value. That's why decentralized state in PSYC needs to be persistent by means of packet ids in order to provide a generic means of sharing global state in a scalable way.
And now to the specification of state:
There is a set of entity variables associated with each context. They are called the state.
Contexts update their state via the =, + and - operators.
To synchronize with a context one has to send a '?' operator on a line by itself to it, with the _target being the uniform of the context. . You MAY combine this with a method, or leave the method out. The meaning of '?' is independent from it.
| :_target psyc://psyced.org/~elmex#friends ? |
The answer from the state is a state reset packet:
| :_context psyc://psyced.org/~elmex#friends :_target psyc://127.0.0.1:-3234/ = =_list_members |psyc://psyced.org/~lynX|psyc://hancke.name/~fippo |
Notice the leading lonely '=', which tells the _target to reset the saved state of the _source.
Again, you MAY provide a method along with this packet, should you want to combine the meaning of '=' with the meaning of such method.
Further updates of the state are either sent explicitly, or the changes are transmitted along with regular context packets, such as _notice_context_enter and _notice_context_leave.