Such an environment is characterised by a high degree of change in the number of participants, change in the connectivity between those participants, and change in the synchrony of collaboration - collaborators may be sitting next to each other or in different time zones. Programmers need a framework that makes it easy to create good collaborative, nomadic applications. They want applications that adapt to mobility, adopt a collaborative posture, but retain the richness and control of desktop applications.
Joyce is a framework I developed at Microsoft Research Cambridge for creating such applications. Joyce is an adaptation of MVC that allows multiple instances of an application to edit a shared model. Joyce implements a fully decentralized architecture in which replicated copies of the model are modified individually by the collaborators; the framework keeps a local replica synchronized by tracking the modifications made throughout the whole group. The framework is robust to changing connectivity and can support any mixture of synchrony. s
Joyce implements an operation-based optimistic replication system. Applications remain responsive by allowing modifications to the local state without regard to other members of the group and without taking global locks on the model. The framework keeps a log of the modifications made along with the semantic invariants between those modifications (for example if two modifications should be atomic or in a prescribed order).
This local log forms part of a larger structure called the multi-log that contains similar entries for the other members of the group. The multi-log is kept up-to-date with an epidemic propagation mechanism that uses sequences of pair-wise exchanges between 'neighbouring' members of the group (members with a direct connection). During an exchange a member transmits the changes it has made and receives the changes its neighbour knows about but it does not. This scheme, originally used in Bayou, ensures that one member can receive updates from another without needing a direct connection. Note that it is not required or expected that a group will be fully connected, indeed the membership of a group can never be completely determined since members can join and leave at any time. In spite of this, all updates will propagate to all members given sufficient connectivity. In building the multi-log this way, the framework gradually forms a semantic graph of the activity within a group:
From this semantic graph the framework determines what remote actions it can replay and in what order (i.e. we reconcile by determining the maximum non-conflicting sub-graph of the semantic graph). Non-conflicting operations are replayed against the local model, subject to filtering.
The user can filter which actions are applied to his model and can also hint to the reconciler that some actions are more important than others. For example, most studies indicate that bad user experience is correlated to a feeling of loss of control over an application, particularly its user interface. A user may wish to be aware of activity elsewhere in the group but does not necessarily want remote changes to be automatically applied to his local state, possibly negating his own changes.
Joyce can be instructed to reconcile but not apply remote changes and that local changes take precedence over remote ones. If the reconciler detects a conflict between a local and a remote change it will reject the remote one; it will not apply the remote modification or its dependants but will retain the information in the multi log. In this way the user remains in full control of his local application whilst being fully informed of activity elsewhere in the group.
Multi-log filtering allows Joyce applications retain the user control exhibited by desktop applications while still participating in ad-hoc collaborative groups. If an event happens that the local user should know about then the framework will call into the application to report the event without interrupting the user's focus of attention. For example, when Babble is informed of remote changes that conflict with local ones it highlights the conflicting content with a faint red background, but the user is not compelled to immediately resolve.
By filtering the multi-log the user 'projects' a subset of the group activity onto his local model and, by extension, into his visual interface.
This projection is also used to supply a selective undo/redo service to Joyce applications. Most mainstream undo/redo systems are stack-like in that modifications must be undone in strictly reverse order; this is because detailed semantics between commands are not recorded so the state must be restored to the way it was when the original command was run if the undo is to be safe. But Joyce has a multi-log that records precisely this information; to perform a selective undo in Joyce the user simply picks out the modification that he no longer wishes to apply to his state, instructs the framework to re-reconcile without that action and its dependants and applies the resulting schedule (in reality this process is heavily optimised in applications such as Babble but this is the general principle). In Joyce applications undo/redo often evolves into a system for exploration rather than error correction since it is intuitive and non-destructive.
An important philosophy of Joyce is that the user's data should be his main, preferably his only, focus of attention. To this end the framework provides automatic persistence (i.e. automatic saving) to applications. One or more entities called storage nodes can be configured as members of a Joyce group. These nodes consume the traffic flowing through the group and persists the resultant multi-log to backing store. It is envisioned that the storage nodes are more stable and contactable than collaborator nodes and can serve to prevent group connectivity from degrading to complete disconnection. Further, a common configuration is for devices with the appropriate resources to run storage nodes that join the collaborative groups of each Joyce application running on the device to persist that group's data locally.
FIGURE
Instead of non-intuitive filenames Joyce users take snapshots of their application data that correspond to milestones in the editing process. A snapshot is a binary image of the user's local state which is annotated with the vector clock of the multi-log when the shot was taken plus whatever meta-data the user provides. Snapshots are managed automatically by storage nodes and can be recalled by applications at any time.
FIGURE?
If a group member disconnects or crashes the act of re-joining the group, and re-contacting the storage node, ensures that the minimum of data is lost. On re-connection an application can either replay the entire multi-log or load an appropriate snapshot and replay the sub-logs subsequent to that snapshot; effectively restoring the state. This imparts a constancy to a Joyce application in that the data modified becomes the user's sole focus of attention; there are no distracting interactions with a 'filesystem' to find or restore application data. See the description of Babble for a practical example of using snapshots.
Joyce was implemented at Microsoft Research Cambridge using .NET. The immediate focus now is creating a streamlined Java framework that encapsulates the same concepts and is re-distributable. We expect the kinds of application Joyce was designed to foster to lead to some interesting questions in the fields of user-interface, application construction, and security.
