Sie sind auf Seite 1von 20

CRTE: Collaborative Real-time Editing

Collaborative real-time editing of plain text using Operational


Transformations and Vector Clock timestamping.

Reuben Braithwaite (656006) Junyuan Liu (805276)


rbraithwaite@student.unimelb.edu.au junyuanl@student.unimelb.edu.au

Aman Lal (791650) Jigar Thakkar (800301)


amanl@student.unimelb.edu.au thakkarj@student.unimelb.edu.au

Abstract Collaborative Real-time editing has become an essential tool for many distributed
workplaces. We present an introduction to the main algorithms that allow collaborative real-time
editors to achieve their primary goals of controlling concurrency and maintaining document
consistency, whilst also achieving their usability goals. We also present a simple implementation
for collaborative editing of plain text documents.

Keywordscollaborative editing; real-time; operational transformation; dOPT;


vector clock; consistency maintenance; groupware;

COMP90020: Distributed Algorithms. Semester 1, 2017, University of Melbourne.

1
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

I. INTRODUCTION
Since the advent of the Web 2.0 technologies collaborative real-time editing (CRTE)
systems have flourished. Products such as Google Docs and Office365, which allow
collaborators to work together in real-time from different physical locations, have become
commonplace and an essential component of many distributed workplaces.
The essential problems that CRTEs must solve are those of distributed concurrency control
and maintaining correctness and consistency amongst collaborators, or peers.
However, in addition to these essential problems there are a number of human-related
issues impacting CRTEs that do not affect other distributed systems to the same extent. These
usability criteria make the use of more general distributed problem solvers algorithms and
techniques that are widely used in distributed software less capable of achieving these
primary goals.
CRTEs are interactive systems, and need to maintain a high level of liveness. That is, the
system should have a level of responsiveness that is comparable to the regular, non-
collaborative editors that users are used to. Furthermore, this responsiveness should also
apply to changes made remotely by other peers. Changes made by one peer should be visible
in near real-time to all the other peers. If this latter property is not fulfilled, peers changes
would rapidly diverge and a state of confusion would arise amongst collaborators.
These usability requirements exclude the use of, for example, locking and mutual
exclusion techniques. If such techniques were applied to this problem a systems
responsiveness would suffer proportionately to the number of connected users. When
confounded by network latency these strategies would deliver poor usability and an
ineffective product.
The most widespread solutions are found in the family of algorithms known as
Operational Transformation. These algorithms achieve concurrency control, maintain
consistency and correctness and allow systems to remain highly responsive. Most versions of
Operational Transformation employ a further, more general, distributed algorithm, the Vector
Clock, as a means of achieving partial orderings.
We will conduct a brief background survey of Distributed Mutual Exclusion, Matrix
Clock, Snapshot and Operational Transformation algorithms, in addition to a more detailed
discussion and analysis of Operational Transformation and Vector Clocks. Finally, we will
present a simple implementation of a CRTE, using the Operational Transformation and
Vector Clock algorithms.

2
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

II. BACKGROUND SURVEY


A. Distributed Mutual Exclusion
What is Critical Section and Mutual Exclusion?
Any code that accesses a shared resource is called the critical section. Multiple nodes
trying to access a shared resource can lead to unexpected behavior and to safeguard the
consistency of a shared resource we perform mutual exclusion such that at any given
moment only one node can enter the critical section.
For the context of Distributed Algorithms project, we surveyed 2 kinds of mutual
exclusion algorithms:
1. Token less mutual exclusion
2. Token based mutual exclusion
Both these types of mutual exclusion algorithms were based in a similar setting and were
evaluated for efficiency.
System Description:
We have a computer network with N nodes which do not have any shared memory and
utilize message passing to communicate. There is no guarantee that messages will be
received in the same order they were sent and the delay in communication cannot be
predicted.
Token less mutual exclusion:
In 1981 RICART and AGRAWALA presented a token less algorithm which works as
follows:
If a given node i wants to enter the critical section it sends a request to all
other nodes in the system.
The request message comprises of a sequence number and the identifier of
node i. The identifier and the sequence number define the priority order
among incoming requests.
Any receiving node sends a REPLY message to node i, immediately if the
node is not requesting or the request of node i has priority over the receiving
node, otherwise node j will defer the reply until after node js request is
granted.
Node i can enter the critical section only when it receives a REPLY from all
nodes in the system.
Now this algorithm takes about 2*(N-1) message exchanges to perform each mutual
exclusion.
Token based mutual exclusion:
This algorithm mentioned above was trumped by a token based mutual exclusion
algorithm proposed by ICHIRO SUZUKI and TADAO KASAMI in term of efficiency
which requires at most N message exchanges to perform each mutual exclusion. The
algorithm is more efficient and solves the problem of starvation and deadlocks in a first
come first serve manner to some extent. The algorithm works as follows:

3
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

Each node maintains an array RNi[N] where i is the identifier and N is the number
of nodes in the system. This array is present at each node and stores information
of all other nodes in the system.
The algorithm uses a token which contains a queue which contains the nodes that
request for the critical section and an array - LN [N] which contains the latest
sequence number executed by the node.
An incoming request is accepted only is RNi[j] < s where s is the sequence
number of the request, if this condition is not true this request is treated as an
outdated request.
A requesting node i broadcasts request message (i,s) and changes its sequence
number in its array RNi[i].
Receiving nodes check if the request is outdated or not and update there RNi.
When the node holding, the token receives the request and is not in the critical
section it places the sending node in the queue.
This node sends the token to the node on the top of the queue. When the node i
receives this node, it can enter its critical section.
Hence the algorithm requires N-1 request message and one message containing the token
to perform a single mutual exclusion. For the purposes of building a collaborative real
time editor using mutual exclusion was not the best approach as the system should allow
for concurrent updates to the shared document. This problem of concurrent updates was
further solved using operational transform techniques.
B. Matrix and Vector Clocks
1. What is a matrix clock?
In an asynchronous distributed system with multiple nodes, we can use vector clock to
denote the sequence of events including value changes or massage passing. However, the
vector clock could only give limited information about global state from an individual
view. In a matrix clock system, the time is represented by a list of vector clocks. As for
process pk, it maintains a matrix mti[1n,1m] where:
mti[i ,i] denotes the local logical clocks of pi and track the progress of the computation
at process pi.
mti[i ,j] represents the latest knowledge that process pi has about the knowledge of pj
has about the logical local clock of pj. The entire matrix mti denotes pis local view of
the logical global time. (Garg, 2002)
Form one point of view, the matrix clock extends the 1-dimensional vector clock into n-
dimensional stage where n is determined by the number of nodes, or normally we say
processes. From another point of view, matrix clock can be generalised as a set of vector
clocks, and is a more sophisticated algorithm for capturing chronological and causal
relationship in a distributed system. In general, matrix clock can deliver much more
information, but it also increases computation and storage consumption as well. One of the
task while implementing a matrix clock is to leverage the trade-off between more
information and higher complexity.
2. The implication of matrix clock

4
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

Matrix clock initially is employed to discard the obsolete information in a replicated


database. Here is an example:
In an asynchronous distributed system, from pis perspective, its obvious that mti[i ,j]
contains all the properties of other processes local stage. It implies that pi should also
know that other processes pk (k i) knows pis local time has progress till t (Raynal &
Singhal, 1996). Furthermore, pi can guarantee that all the other processes will never send
information with local time which is less than t. Hence, in many applications, process pk
can use this fact to discard obsolete information due to it already knows what kind of
messages are out-of-date.

3. Possible optimization for matrix clock


One of the problems with matrix clock is that its costly to implement (Ruget, 1994). It
indicates that, in an asynchronous distributed system that has n sites, a functional matrix
clock requires storage and communication overhead of size O(n2). Therefore, it becomes
infeasible when the number of site in the system becomes large.
In recent researches, an efficient incremental algorithm which reaches the storage and
communication overhead of size O(n) when all the sites within a system are properly pre-
defined. This approach will require all the sites suit certain topological distribution, and
thats basically the reason why overhead decreases. The other alternative solution is called
k-matrix clock. Its an approximation comparing to the original matrix clock that can
achieve the storage and communication overhead of size O(kn) (Ruget, 1994). The k-
matrix clock can be applied to fault-tolerant protocols especially for systems with crash
failure semantics such that the faults caused by concurrency would be bounded by k-1.

C. Operational Transformation
Here we offer a brief introduction to the operational transformation algorithm. We will
describe its origin and basic form
The first collaborative real-time editor is widely considered to be that which was
demonstrated by Douglas Engelbart in 1968. This presentation The Mother of all Demos
demonstrated many features which have since become ubiquitous parts of personal
computing. The mouse, graphical interfaces, video conferencing and hyperlinks were also on
show. Like most of these other functionalities, collaborative editing took a long time to make
it to widespread personal computing.
Operational Transformation was first described by Ellis and Gibbs1 in 1989. The
algorithm they described, known as dOPT (distributed operational transformation), was
implemented in their software GROVE (Group Outline Viewing Editor). Ellis and Gibbs
identified the concurrency control problem related to CRTEs and noted that more generic
approaches such as locking were unsuitable for CRTE implementations. The solution that
was proposed resolved conflicts, preserved intention and causality and maintained
consistency throughout the distributed versions of the shared document.
Their solution is centered around the idea that every change can be expressed as a
combination of two types of atomic operation. A user either inserts a chunk of text or deletes

5
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

a chunk of text, and the state of the document can be expressed as a log, or history, of these
operations.
Insert( integer:index, string:value ) Delete( integer:index, integer:length )

Each change is logged to an operation history as one or more of these operations, and
those operations are broadcast to peers. Upon receipt, each peer checks its own operation
history, and transforms the incoming operation against any concurrent operations that have
been performed locally. The transformed operation is then applied to the local document and
written to the local operation history.
The figure below demonstrates a comparison between two sequences of events one that
transforms received operations and one which does not.

A B A B

ccc ccc ccc ccc

Oa = Insert(0, aaa) Ob = Insert(3, bbb)


Oa = Insert(0, aaa) Ob = Insert(3, bbb)

aaaccc cccbbb

aaaccc cccbbb

Ob= Transform(Ob) Oa= Transform(Oa)

Ob = Insert(3, bbb) Oa = Insert(0, aaa)


Ob= Insert(6, bbb) Oa = Insert(0, aaa)

aaabbbccc aaacccbbb aaacccbbb aaacccbbb

Figure 1: Comparison of concurrent insert operations with and without Operational Transformation

We see that where an insert operation is received and applied without transformation,
peers documents diverge and consistency is lost. Similarly, a delete operation will also result
in divergence. However, when received operations are transformed, peers documents
maintain their consistency. It is worth noting that while consistency is maintained in each
peers document, their individual operation histories will contain subtle differences but
differences will still result in a consistent state between peers.
The basic form of the transform function is quite simple. Below, we see the transformation
of the received operation Or against the history operation Oh.

6
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

function Transform(Or , Oh):

if ( Or.index > Oh.index ) or ( Or.index == Oh .index and Or .peer < Oh .peer ):

if Oh.operation == delete:

Or .index -= Oh.length

if Oh.operation == insert:

Or .index += Oh.value.length

return Or

Figure 2: Basic transform function

When an operation is transformed, its index its position in the text is compared to
that of the operation it is transforming against. The received operation needs to be
transformed if its index is greater than the index of the historical operation. If its index is less,
the historical operation has no effect. These two cases result in a consistent and correct state
between peers, but there the final case, where the index is same, presents a dilemma. The two
peers have tried to insert, or delete, at the same index. This gives the dilemma of having to
decide who goes first. The solution is to break this tie using an agreed priority. A standard
way to do this is to use the peers ids as a tie-breaker, but which peer is given priority is not
important. What is important is that this priority and therefore the result of the
transformation and the effect it has on the shared document is consistent for all peers.
Ellis and Gibbs did not present a full proof of correctness, but offered an outline of the
form this proof should take, the problems that must be solved and the properties the algorithm
must maintain in order to be considered correct. These properties are known as the
consistency model.
The main problems that must be solved are divergence and causality-violation, and these
two problems essentially defined the properties of the consistency model: convergence and
causality preservation.
Subsequent work, such as Sun and Ellis2, has shown the correctness of the dOPT algorithm
to be flawed and have proposed that the consistency model be expanded. Indeed, several
different consistency models have been described and applied to numerous variations of the
Operational Transformation algorithm, and we will discuss these models below.
While dOPT and other variations focused on linear documents such as plain text real
world applications and requirements have pushed work into the development of more
sophisticated algorithms, which, while still based on the core ideas of Ellis and Gibbs dOPT,
have adapted to work with rich data structures and the kind of documents that people need to
produce. Davis, Sun and Lu3, for example, discuss rich-text documents which form tree-like
structures based on publishing conventions and semantic meaning, and describe the
generalization of the operational transform to deal with markup languages. It is evident that
such requirements are not only necessary, but are met by the major CRTEs. We will discuss
this approach below.

7
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

D. Snapshot
There are many algorithms and research papers available with various theories describing how
to take snapshots for a distributed system but most of them are trivial. Some of them are not
applicable in the real world and some are incorrect as written by Chandy and Lamport in their
famous and well know paper in distributed snapshots. The reason for incorrectness of these
algorithms is that various concepts of distributed system are not defined properly. Chandy and
Lamports research defines these distributed system concepts. All the research work published
after their paper either extends their idea about distributed snapshots or is a variation of their
algorithm. For example, Chandy and Lamport's paper is applicable to FIFO (First in first out)
and asynchronous system and using this algorithm Friedemann Mattern has published an
algorithm which is applicable to non-FIFO channels. He has optimized the algorithm using
GVT (Global Virtual Time).
Chandy and Lamport's algorithm forms a baseline for snapshot algorithms. The main
prerequisite to these algorithms is that it should not interrupt the actual system and a correct
algorithm always captures all process states as well as messages in all channels. Process states
can be anything based on the type of application. Also, there should not be any single point of
operation, this means that any process in the system can start capturing a snapshot.
In the Chandy-Lamport algorithm, any process that wants to start on capturing a system
snapshot will first records its own states, and after that, it sends marker messages to other
processes and will also start to listen for marker messages on which it already sent. When
another process receives a marker message, it records its own state and sends marker message
to all other processes including the one from which it received. When the first process receives
marker messages from all other processes, it stops recording channels. So, after the end of the
algorithm, we get pieces of the snapshot which we can put together to create one single
snapshot.
Here is one simple example of how Chandy-Lamport algorithm works.

Figure 3: Example of the Chandy-Lamport algorithm

8
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

III. DISCUSSIONMATRIX AND VECTOR CLOCKS


A. Comparative Analysis
In the context of collaborative real-time editor, we need to use a timestamp method to
order all the incoming operations from client or peers. Since its very likely to have
concurrency issues in a collaborative editor, conflicting operations need to be ordered by their
timestamp so that we can ensure the consistent version of documents on each peer.1
This section will analyze two types of timestamp approaches: vector clock and matrix
clock, and compare their pros and cons. At the end, we will choose the algorithm which is
more compatible with our task.
1. Definition of VC and MC

Vector clock is an algorithm for generating partial ordering of events in a distributed


system, one clock per process. It could be used as an improvement of Lamport clocks: two
events timestamped by vector clock can be ordered by happened-before relationship and
are concurrent by comparing their vector timestamps. The vector clock has following
properties:
If V(e)<V(e) then e e;
Vj[i] Vi[i].

Matrix clock is a generalization of the notion of vector clock. Apart from having the latest
state of its local process, it also contains the current state of other processes known by
itself. The sending and receiving events corresponding to certain message-passing action
can be unambiguously matched through matrix clock. Matrix clock allows a process to
establish a lower bound on what other nodes know, which means it can acknowledge if the
incoming information is obsolete or not. On the other hand, matrix clock is also costly
implement due to it requires much higher storage and communication overheads.

2. Example of VC and MC

What would VC look like in a CRTE system


In the context of a collaborative real-time editor, there is no central server which could
maintain the consistent version of the latest document. All the peers have a local copy of
document on its node, and the ultimate objective of our project is to ensure that all the
local documents are consistent despite of multiple users amend the document
simultaneously.

In terms of vector clock, there are two types of operation needs to be timestamped: the
operation sent from editor when the user changes the content on the editor; and the
operation from other peers when there are changes happened on other peers local
document.

9
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

Once the server receives an operation from the editor, the local document needs to be
updated according to this operation. The server node will increment current vector clock
and timestamp this operation, then insert it to the queue. Next server will broadcast this
operation with latest vector clock to other peers to request other peers changes their local
document.
When a server receives an operation from other peers, it firstly increments its own vector
clock, and then merges the vector clock on this incoming operation and its local vector
clock. The incoming operation with new timestamp will also be inserted to the queue.
Before writing all the operations in the queue into local document, the server will check
the concurrency issues. If one operation has no concurrent conflict, it will be directly
written into local file. But fi there are concurrent operations, server will implement
Operational Transformation algorithm to resolve those conflicts and then write them into
local file.
What would MC look like in a CRTE system

The implementation of matrix clock shares most of similarities with vector clock. The
server will send and receive operations timestamped by matrix clock, and increment,
merge and compare the matrix clock in the same way with vector clock.

In the context of having a collaborative real-time editor, all the operations will be
broadcasted, which implies that each operation will be received by all peers at the end. In
this sense, matrix clock seems to be redundant. For example, matrix clock piggybacks an
information which is process i knows what process j knows about the system, yet the
knowledge of pi will always be the same the pj due to pi and pj both received previous
operations from other peers in the system. In another word, matrix clock doesnt
contribute any useful information to one peers, in addition it highly increases the
complexity of computation and the volume of data to transmit between peers.
B. Application Domains and Future Directions
One typical application of vector clock and matrix clock is system of asynchronous
distributed message-passing. Vector clock are widely used in areas like checkpointing,
maintaining the consistency of duplicated files, termination detection and debugging. Matrix
clock is more likely to be adopted in protocols that should discard obsolete information, such
as distributed database and replicated log.
Given by two different level of knowledge of the whole system, the purpose of these two
clock methods is to achieve the eventual consistency. However, with the size of nodes and
message-passing increasing, the accumulated records of log and history will be impact on the
system performance, in this case, matrix clock will be more preferable due to it tells the
current state of each node in this system. But sword has two edges, in terms of tasks like
debugging or checkpoint, what the user concerns is the exhaustive steps through the entire
process. At this point of view, vector clock becomes more desirable in these situations
because we want to track and trace the history where no information is discarded.

10
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

IV. DISCUSSIONOPERATIONAL TRANSFORMATION


A. Comparative Analysis
A comprehensive analysis of the numerous variations of the Operational Transform
algorithms is well beyond the scope of this paper. Instead we present key issues, which affect
most if not all implementations and versions of operational transformation.
As stated above, the consistency model identified by Ellis and Gibbs original dOPT
algorithm featured two essential properties that must be maintained for correctness: causality
preservation sometimes referred to as precedence and convergence.
For the convergence property to be satisfied, all copies of the shared document must be
identical. For the causality preservation property to be met, whenever an operation Oa
causally precedes another operation Ob, then Oa must be applied before Ob for all peers.
In most variations of operational transformation, causality preservation is ensured by
timestamping operations using vector clocks. These timestamps ensure a partial ordering of
operations, and this partial ordering is sufficient to meet this property.
Sun and Ellis determined that, for convergence to be maintained, the dOPT algorithms
transformation function must confirm the following equivalence4:
Where !" and !# are independent, concurrent operations, and
where !" = &(!" , !# ) and !# = &(!# , !" ), it must be that:
!" !# !" !#
That is, any two independent and concurrent operations will, when transformed against
each other using the algorithms transform function result in an equivalent state. So it is that
different peers can reference operation histories containing subtly different operations, which,
when combined, converge at an identical document state.
However, it was observed that dOPT failed in some cases. This was observed by several
authors, and became known as the dOPT Puzzle.
The solution to this puzzle was developed in the adOPTed algorithm5, and proof of this
solutions correctness was demonstrated by Lushman and Cormack.6
According to adOPTed, a second transformation property must be added to guarantee
convergence:
For any !,
& & !, !" , !- # = & & !, !# , !- "
The consistency model for the adOPTed algorithm had now expanded from the original
dOPT consistency model by adding a second transformation property.
In fact, several additional properties have been identified as being of importance to the
operational transformation class of algorithms.

11
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

B. Application Domains and Future Directions


Operational transformation algorithms have traditionally used just two operations: insert
and delete. These primitive operations are more than capable of enabling collaboration on
simple, linear documents like plain text files, but what would happen if we tried to apply this
approach to a more complex document. Perhaps something with an organized markup
structure, like HTML or a Word document?
Such documents are tree structures. The Document Object Model of HTML for example,
defines a hierarchical, nested collection of nodes. In this context, what does it mean to insert
or delete?
Far from being a hypothetical question, this is a baseline requirement for operational
transformation. No one is wildly interested in collaboratively editing plain text, but products
like Google Docs and Office365 are incredibly useful. So it is apparent that to facilitate
functionality that people want, operational transformation must be extended. Furthermore, it
should be clear that this is exactly what has happened.
Davis, Sun and Lu7 note that while operational transformation is the state of the art in
synchronous collaborative editing it is traditionally unable to model the kind of metadata and
structure required for more complex, formatted documents. They propose a new data model
for using operational transformation with rich documents.
This data model is a tree of nodes. Each node contains several properties:
A Type property: different types have different properties and allowed values. E.g.,
paragraph, image, list each of which allow different properties
A Subnode property: a list of subordinate nodes
A Content property: a string, for example
Metadata properties.

This structure conforms to the Standard Generalized Markup Language specification.

type paragraph
children

type text type text type text


text The cat text sat text on the mat.
italic no italic yes italic no

Figure 4: Tree structure of a simple paragraph

With this more sophisticated data structure, a more sophisticated addressing system is
required to identify where to perform operations. The required features of a suitable
addressing convention are: locatability; consistency; uniqueness. That is, it must be a

12
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

straightforward task to identify and locate each node, the same address should refer to the
same node for all peers, and each address refers to one node only.

A[]

A[0] A[1] A[2]

A[0, 0] A[0, 1] A[1, 0]

A[1, 0, 0] A[1, 0, 1]

Figure 5: Example addressing convention for tree structure

We now consider the adapted set of operations, Insert, Delete and Change.
Insert and Delete operations are referred to as structural operations. They change the
structure of a tree. The new operation Change is not structural, but rather is a mutation. The
data contained with a node changes without altering the structure of the tree.
Insert and Delete in this model share a new set of parameters to replace the traditional
index parameter. For the functions Insert(N, n, M, T) and Delete(N, n, M) N is the address of a
node, n is the nth child of N, and M is the name of the node. The additional parameter T for
an insertion is the type of the node.
The function Change(N, k, f,) will alter node N, so that the value v for property with key
k is altered to f(v). Thus, an arbitrary number of transitions can be applied on the basis of the
transition function f(). This technique allows the algorithm to loosely couple mutations and
operations, thereby keeping the operational transformation as simple as possible, while
allowing the system to be as extensible as possible.
The consistency model for this enhanced algorithm is similar to existing consistency
models for other operational transformation algorithms. The system must maintain
convergence, causality preservation and intention-preservation.

13
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

V. IMPLEMENTATION DETAILS
A. Purpose and Scope
The purpose of this implementation is to develop working models of the Operational
Transformation and Vector Clock algorithms. A correct implementation of these two
algorithms should result in a consistent and correct CRTE.
Though boiler plate code is required to provide a framework for these implementations,
we will endeavour to keep this scaffold to a bare minimum. For example, though the system
needs to cummunicate with an arbitrary number of peers, we will limit any process of peer
discovery to the minimum required to connect those peers. In practice, this means a manually
defined list of peers, all of which must be present to achieve proper operation of the system.
Likewise, error handling is minimal, and communication is conducted via synchronous
http rather than the preferred asynchronous http that a real world system would employ.
B. System Overview
Though many CRTE systems such as Google Docs use a centralized authority, this
system is a fully decentralized and distributed network of peers. Each peer in this network
maintains its own copy of the shared document and a correct implementation will result in
each of these documents being identical.

:peer 1 :peer 2 :peer 3 :peer 4 :peer n

abcde abcde abcde abcde abcde

Figure 6: Distribution model

14
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

Each peer contains two components: Client and Server. The former is a simple text editor
that the user accesses in a web browser and which communicates with the latter via
asynchronous http. The server itself is a simple http server constructed using the Python
Flask library. This server communicates with its client and other peers, and reads and writes
plain text and JSON to the file system.

:Client :Server :Filesystem

Front Operation
Controller History
Observer

Peers Documents Transaction


Editor Controller Controller Queue

Peer Document Document

Figure 7: System Component Diagram

C. System Description
Below we describe the systems components.
Client
The client is a simple html page, index.html, containing a text area where the user edits the
shared plain text document. This html initializes with two javascript modules:
plainTextEditor.js and observer.js. Both modules use the javascript module pattern. The
former initializes an html textarea, and the latter observes that textarea for changes, sends
changes to the server and receives changes from the server.
Server
The server is a simple Python application, which is designed with an MVC architecture
and which uses a Flask http server in a Front Controller pattern. Thus, all requests are
intercepted by the front controller crte.py, before being directed to the relevant controller for
Documents or Peers.
D. System Interaction
The two main sequences of interest to this project. The first is when a peer initiates a
change, and the second is when a peer receives a change. These sequences are described
below.

15
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

1) Initiating changes
When the user makes a change in their browser, that event is detected by the editors
observer. To find a balance between fine granularity and minimizing http requests, the
observer waits until the user pauses before sending the new text to the server. The request is
handed to the Document, which runs a Myer Diff algorithm to find differences between the
stored document and the updated text from the client. The results of the diff are used to create
a series of insert and delete operations. On receiving these operations from the client the
server increments its local vector clock using the increment function, packages it into a
transaction, along with a vector timestamp and the peer id.
This transaction is written to the local operation history and its operations applied to the
document file before it is broadcast to each of the networks other peers.

Front Documents Peers


User Editor Observer Document Peer
Controller Controller Controller

change()
detect()
POST(text)
update(text)
D = find()

D
update(text)
d = diff(text)

o = build
operations(d)

vt = vector
timestamp()

T=
transaction
(o, vt, pid)

write
history(T)

write
document(T)

broadcast(T)

each
POST(T)

T
T
T

perform(T)

each T op

apply(op)

Figure 8: Initiating a change

16
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

2) Receiving changes
Two discrete sequences handle receiving and integrating changes from a remote peer. In
the first, an http request is received containing a Transaction. Once the transaction is
received, the receiving peer increments its own local vector clock and merges it with the
incoming vector clock to have an updated local vector clock. The incoming transaction is
placed into an operation queue, where it waits until the system is ready to deal with it.
The second sequence handles the actual integration. The client polls the server to request
any changes, and the Document is asked to integrate. As each transaction Tq is removed from
the transaction queue its vector timestamp is compared with the operation history to find
concurrent transaction. Then, for each concurrent transaction Tc, Tq is transformed into Tq.
Tq is written to the operation history, applied to the document and each operation is returned
to the client so that changes can be applied to the actual editor.

Front Documents Peers


Document Peer
Controller Controller Controller

POST(T)
receive(T)
D = find()

D
receive(T)
queue(T)

User Editor Observer

poll()
integrate()
D = find()

D
integrate()

while Tq = CT = concurrent
Transactions(Tq)
dequeue()

Tq =
Transform (Tq, CT)

write
history(Tq)

write
document(Tq)

ops += Tq.ops

ops
ops
ops

perform(ops)

each op

apply(op)

Figure 9: Receiving a change

17
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar
E. Algorithms and Data Structures

1) Operational Transformation
Pseudocode of the major operational transformation functions is presented below.

function CreateChanges(text): {
d= MyerDiff(text, old_text) peer_id: integer,
ops = Operations(d) operations: [
vt = VectorTimestamp() { op: insert, index: integer, value: string },
T = BuildTransaction(ops, vt, pid) { op: delete, index: integer, length: integer }
WriteToLocalDocument(T) ],
WriteToLocalHistory(T) timestamp: [ int1, int1, intn ]
BroadcastTransaction(T) }

Figure 10: Initiating a change, and transaction format

function ReceiveTransactionFromPeer(T): function Transform(Tq, CT):


Enqueue(T) for Tc in CT:
for Oc in Tc:
for Oq in Tq:
function Poll():
if Oq.i > Oc.i:
O1..n = Integrate()
Oq = TransformOperation(Oq, Oc)
return O1..n
else if Oq.i == Oc.i and Oq.pid < Oc.pid:
Oq = TransformOperation(Oq, Oc)

function Integrate():
while Tq = Dequeue(TQ):
function TransformOperation(O1, O2):
CT = concurrentTransactionsInHistory()
if O2.operation == delete:
Tq = Transform(Tq, CT):
O1.i -= O2.length
WriteToDocument(Tq)
if O2.operation == insert:
WriteToHistory(Tq)
O1.i += O2.value.length
return O1
Figure 11: Receiving and integrating changes

18
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar
2. Vector clocks
Below is the pseudocode for the major vector clock operations and a list of events which should trigger
these operations.

function increment(localvectorclocktuple,index):
return localvectorclocktuple[index+1]

function merge(localvectorclocktuple,peervectorclocktuple):

for i = 0 to size
localvectorclocktuple[i] = max(localvectorclocktuple[i],peervectorclocktuple[i])
return localvectorclocktuple

function compare(localvectorclocktuple,peervectorclocktuple)
for i=0 to size
if( localvectorclocktuple[i]<peervectorclocktuple[i])
return -1
else if ( localvectorclocktuple[i] == peervectorclocktuple[i] )
return 0
return 1

function is_concurrent(localvectorclocktuple,peervectorclocktuple)
return (localvectorclocktuple != peervectorclocktuple)
and compare(localvectorclocktuple,peervectorclocktuple) == 0

EVENT 1 : USER TYPES IN THE EDITOR , AN OPERATION IS GENERATED


LOCAL_VC = increment(LOCAL_VC,Peer_No)

response = documents_controller.update_document(request, LOCAL_VC, Peer_No)

transaction = response['transaction']

Broadcast_transaction(transaction)

EVENT 2 : A MESSAGE IS RECEIVED FROM A PEER , CHECK IF INCOMING REQUEST IS FROM A KNOWN PEER

if peers_controller.authorisesIP(request.remote_addr):

transaction = request.json['transaction']

LOCAL_VC = increment(LOCAL_VC, Peer_No)

timestamp = tuple(transaction['timestamp'])

response = receive_transaction(request)

LOCAL_VC = merge(LOCAL_VC, timestamp)

19
COMP90020: CRTE: Collaborative Real-time Editing. Braithwaite, Lal, Liu, Thakkar

REFERENCES

1
Ellis, Clarence A., and Simon J. Gibbs. "Concurrency control in groupware systems." In Acm Sigmod Record, vol. 18, no.
2, pp. 399-407. ACM, 1989
2
Sun, Chengzheng, and Clarence Ellis. "Operational transformation in real-time group editors: issues, algorithms, and
achievements." In Proceedings of the 1998 ACM conference on Computer supported cooperative work, pp. 59-68. ACM,
1998.
3
Davis, Aguido Horatio, Chengzheng Sun, and Junwei Lu. "Generalizing operational transformation to the standard general
markup language." In Proceedings of the 2002 ACM conference on Computer supported cooperative work, pp. 58-67. ACM,
2002.
4
Sun, Chengzheng, and Clarence Ellis. "Operational transformation in real-time group editors: issues, algorithms, and
achievements." In Proceedings of the 1998 ACM conference on Computer supported cooperative work, pp. 59-68. ACM,
1998.
5
Ressel, Matthias, Doris Nitsche-Ruhland, and Rul Gunzenhuser. "An integrating, transformation-oriented approach to
concurrency control and undo in group editors." In Proceedings of the 1996 ACM conference on Computer supported
cooperative work, pp. 288-297. ACM, 1996.
6
Lushman, Brad, and Gordon V. Cormack. "Proof of correctness of Ressel's adOPTed algorithm." Information Processing
Letters 86, no. 6 (2003): 303-310.
7
Davis, Aguido Horatio, Chengzheng Sun, and Junwei Lu. "Generalizing operational transformation to the standard general
markup language." In Proceedings of the 2002 ACM conference on Computer supported cooperative work, pp. 58-67. ACM,
2002.
8
Mattern, F., 1989. Virtual time and global states of distributed systems. Parallel and Distributed Algorithms, 1(23), pp.215-
226.
9
Chandy, K.M. and Lamport, L., 1985. Distributed snapshots: Determining global states of distributed systems. ACM
Transactions on Computer Systems (TOCS), 3(1), pp.63-75.
10
Mattern, F., 1993. Efficient algorithms for distributed snapshots and global virtual time approximation. Journal of Parallel
and Distributed Computing, 18(4), pp.423-434.
11
Lai, T.H. and Yang, T.H., 1987. On distributed snapshots. Information Processing Letters, 25(3), pp.153-158.
12
Ricart and Agrawala. " An Optimal Algorithm for Mutual Exclusion in Computer Networks Communications January 1981
of Volume 24 the ACM Number 1
13
.Suzuki and Kasami " A Distributed Mutual Exclusion Algorithm Networks ACM Transactions on Computer Systems, Vol.
3, No. 4, November 1985.
14
Chang, Singhal and Liu " A Dynamic Token-Based Distributed Mutual Exclusion Algorithm Dept. of Computer and
Information Science The Ohio State University

20

Das könnte Ihnen auch gefallen