(picture)

June 22, 2002

Groove Tour design, part three.

Groove Tour design, part three. Latency and stuff (or at least, a lead-in to those things).

First off, it helps to understand how Groove's shared-space synchronisation works (at least to some "comfort level"... I'm usually happy just to say that Groove keeps shared spaces in synch, and you don't need to go any deeper than that). When you're building Groove tools, and especially when integrating with other systems, the synch model is quite important. I don't claim to understand the dynamics in detail - I only work with it from the outside, so things may be way off base. But here we go.

In your shared space, transactions happen on the database (database = the space and its contents) when things happen in the space. Users initiate transactions, usually by waving a mouse around or typing. The transactions change the state of the (XML) database underneath. These transactions are also put into message queues directed at the other endpoints of the shared space (the other participants' devices). Eventually, they're quite likely to arrive. Actually, the Groove "dynamics" service pretty much guarantees that the transactions will arrive and be processed, in the same order, on every endpoint of a shared space (and if that fails, your endpoint is "out of synch", and you and every other endpoint in the space is made aware of that synchronization failure, and you can get reinvited to the space if you want).
That guarantee takes some magic. In particular, it means that there's a transaction log associated with each database, and very often (because the network flakes out, or because things simply arrive at different speeds, or because PC clocks are never synchronised, or Joe did some work on the aeroplane and just plugged back in, whatever) you'll find a "missing transaction from the past" arrives. Because Groove has already made a best-effort to keep current state (so that the space doesn't simply freeze if something atomic is missing), the database will roll back a little, insert the newly-arrived transaction, and roll forward again. Bingo. You're up to speed.
(Which then gets into all sorts of transaction-integrity stuff. Don't worry. If you have transaction dependencies - x must happen for y to occur - then there are ways to express that. In the tour, I'm really only interested in very simple sequential, independent, transactions).

To sum that up (it's late... keep this short...) you have an interesting choice when looking at a Groove shared-space. Are you interested in the "current state"? Great; it's always being synchronised with any other participants in the space. Sharing state is incredibly easy: for example you use a propertylist
  PropertyList.SetProperty( sPropName, pValue, nFlags )
where the default flags are GroovePropertyFlag_Serialize + GroovePropertyFlag_Disseminate); or use a RecordSetEngine (which has rather more structure, and indexes, and stuff); or use a DocumentShareEngine (which does binary documents very easily).

But the Tour is concerned instead with tracking changes in state - sequenced events. That's actually just as easy - the events in the Tour are set on a propertylist using the code below. Each event is a "delta", and is disseminated to the other endpoints, and processed when it arrives. But when you receive these events, time can flow both forward and backward. Now that starts to get fun. And more serious discussion will have to wait....!

	var pEl = CreateNewElement("urn:training.groove.net:TourEvent");
pEl.SetAttribute( "Name", sEvent );
pEl.SetAttribute( "Param", sParam );
// some other parameter stuff elided for brevity
pEl.SetAttribute( TOUR_INSTANCE_ID, sInstanceID );
pProps.SetProperty(
sEventType, // we only have types of "bot event" or "client event"...
pEl,
( bDisseminate ? GroovePropertyFlag_Disseminate : 0 ) + GroovePropertyFlag_Serialize );