These are build instructions for a typical unix/linux system which is not MacOSX since you need some special configure switches in that case.
I currently have a kind of ad-hoc rule to keep packages which should be binary compatible in a common directory, but this method may prove wrong, so please give me a note in that case. The following code should be easy to understand for anyone if you also have a look at the possible values of the tcl_platform array:
if {$this(platform) eq "unix"} { set machine $tcl_platform(machine) if {[regexp {[2-9]86} $tcl_platform(machine)]} { set machine "i686" } elseif {$tcl_platform(machine) eq "x86_64"} { # x86_64
set machine "i686" } set machineSpecPath [file join $tcl_platform(os) $machine]
You can look into the coccinella/bin/ directory tree for a few examples.
First of all you need Tcl/Tk 8.5 if you do not already have it. Typically you do not get it from cvs HEAD since that usually points to an experimental version. Instead download it from Tcl Developer Xchange and follow the README.
Some notes on the directory layout. Place all sources dirs in a common directory like:
tcl/ tk/ tkpng/ tktreectrl/ ...
cvs -d:pserver:[email protected]:/cvsroot/tktreectrl login cvs -z3 -d:pserver:[email protected]:/cvsroot/tktreectrl co -P tktreectrl ./configure make make install
The last step is not necessary but makes it easier to identify which components, *.so, pkgIndex.tcl, other .tcl support files, are needed.
cvs -d:pserver:[email protected]:/cvsroot/tkpng login cvs -z3 -d:pserver:[email protected]:/cvsroot/tkpng co -P tkpng ./configure make make install
Useful to obtain safer connections using TLS is the tls package.
cvs -d:pserver:[email protected]:/cvsroot/tls login cvs -z3 -d:pserver:[email protected]:/cvsroot/tls co -P tls ./configure make make install
Depending on how your SSL installation looks like you may need to specify certain configure flags which points to the wanted SSL system. I have noted that some linux users aren't able to load the standard i686 build, but have no idea why. You may find prebuilt binaries for your system here.
The voip system is using the iaxclient which you can grab at:
svn co https://iaxclient.svn.sourceforge.net/svnroot/iaxclient/trunk iaxclient
It depends on portaudio and speex and you may consult the README or mailing lists which versions match since there have been some incompatible changes. Build and install all three, first speex and portaudio, then iaxclient. That done you need to build my tcl package, you can find instructions here.
Iaxclient typically needs the Tcl UDP extension to penetrate NATs amongst others.
cvs -d:pserver:[email protected]:/cvsroot/tcludp login cvs -z3 -d:pserver:[email protected]:/cvsroot/tcludp co -P tcludp ./configure make make install
Support for additional image formats in whiteboards. TODO
Coccinella, like most other Tcl/Tk based applications, is deployed using tclkits and starpacks. There is a very good tutorial describing all this. In short, a starpack is a Tcl/Tk application wrapped up together with a complete Tcl/Tk runtime into a single executable file. At the core there is only one command:
sdx wrap coccinella.exe -runtime tclkit-win32.upx.exe
This line is at the core of the build script, see below. Execute this only if you are not using the build script. See the tutorial for how sdx works.
You can build for any platform on any platform. That is, for instance, I build both linux-x86 and Windows versions on my Mac. You just need to have the proper tclkits to wrap up with. I recommend you use either a unix/linux or a mac system for building. Although it is possible to build on Windows, I have no experience with that.
Important:
Tclkit 8.5.x or later is required.
That said there are essentially two ways to build:
This method I've never tried myself, but Marion Bates has written
a detailed page of how to do it. I think there is a time limited trial download.
I use a simple script on my Mac that builds the Windows and Linux versions. You can use this script for the Mac version as well, but I prefer to use Apples native way of doing this using application bundles, see below.
There are three things you need to download to start with:
This assumes that you have an ActiveState Tcl/Tk installation or something compatible. This distro may include a sdx program, I don't know.
Next you need to get Coccinella's source code from either one of two places:
And then there is, of course, my build script. You need to edit it at the indicated places to suit your directory setup. Note that Coccinella has a separate Subversion directory for tools which also contain build tools.
Then do:
BuildCoccinella.tcl
there also. May need to chmod u+x BuildCoccinella.tcl @@@ Edit
) so the paths point at your downloaded tclkits for each platform.tclsh BuildCoccinella.tcl
On Mac I use Apples native packaging as an application bundle. Either take the latest released Coccinella, open the application bundle by control clicking, replace the coccinella folder with your own.
You can also get any other later TkAqua. Pick the self contained one (TclTkAquaStandalone). You need to copy the Info.plist file, the icon and the PkgInfo file from the original released Coccinella. Replace also the Contents/lib folder with the one in the Coccinella bundle since you do not need all of them. You can also get more detailed info from
(broken URL).
The Subversion and the source distros are complete for Linux-x86, Windows, and Mac OS X, in the sense that no extra packages need to be obtained.
If you build for any other platform you need to obtain and build the
following packages:
Some more fixes are probably needed. Just contact me so we can sort out this.
The simplest way to make custom builds is just to replace parts of the
sources with your own. Typically icons in the images/ directory. My build script has some support for custom builds. You need to edit the script to suit your needs. I have a test example. Just place it in the same directory as coccinella and edit the build script.
The custom build procedure is a bit out of date and will probably be revised, so beware!
This tutorial will help you to translate Coccinella to a new language or to update an existing language catalog.
To avoid double work, you first should contact the current translator(s) of your language, or ask in the forum if you would like to start a new translation. Wait a few days to see whether or not you get a response.
Then, download the latest translation sources and translation template and extract this file.
Proceed by installing a good computer-assisted translation (CAT) program with gettext support, such as Poedit, Lokalize, Kbabel, gtranslator, and Virtaal. Use this program to open the existing XX.po file for your language code. Or use this program to create a new translation using the template.pot file.
Translate untranslated strings, improve strings which are already translated, and/or review fuzzy strings (do not forget to remove the fuzzy status after reviewal). Please do not hesitate to ask in the forum if you have any questions about using the computer-assisted translation program.
Finaly, contribute your new or updated translation XX.po file by filing a new bug entry with attachment.
Your translation will be added to the development version and we will notify you about this. Less than 24 hours later, you can test your translation in the daily build.
Note that some of the menu strings, have an ampersand "&" in their text string. This means that the character following it will be underlined and the "&" be removed from display text. The underlined character corresponds to a keyboard shortcut for that entry. You are free to pick the underlined character which suits your language yourself, but remember that each character may be underlined only once in a menu.
For an outstanding translation usability, we would suggest you to first simply translate all menu entries. Then, you should look at which letters are used for similar menu entries in popular software like Firefox and try to be as consistent as possible when selecting letters, without using letters more than once. Although this will take a lot longer, the quality of your translation will be much higher!
Some of the strings contain one or more "%s". These will be replaced by variables when the string is displayed. You need to see the code if you want to know the replacement variable.
In some cases your language may have a different grammar than English, and there may be situations where the order of the replacement variables must change. In such situations you need to add positional codes. An example describes it best:
{This is the %s and %s attempt} FIRST SECOND This is the FIRST and SECOND attempt {This is the %2$s and %1$s attempt} FIRST SECOND This is the SECOND and FIRST attempt
You just replace "%s" with "%#$s" where # is an integer describing the position.
This page is to track issues with third-party software that have negative consequences for users who are using Coccinella. Issues may be trivial usability problems, critical compliance bugs, strange behaviour, crashes, amongst others. The final goal is to get these issues fixed in the third party software so that Coccinella users can benefit from a better end user experience.
Software | Problem | Cause |
---|---|---|
PyMSNt | Ugly MSN JIDs in Coccinella's GUI | Lacks support for XEP-0106: JID Escaping |
Tlen Transport | Tlen not available as option when adding contact | Patch to fix wrong disco of Tlen transport |
jGGtrans | Automatic login does not work | ? |
JJIGW | Wrong disco registrar type: 'x-irc' instead of 'irc' | Patch to fix wrong disco of JJIGW transport |
One of the core parts of Coccinella is JabberLib, a BSD licensed library written in Tcl. Although the library is included in Coccinella, you also can download JabberLib as a separate download. The development version of the library is available in the Coccinella development repository. JabberLib hides all XML used by the Jabber/XMPP protocols. Additionally, a few test files are included to get you started, and although no documentation is available, there is a brief summary of commands in the prefix header of each source file.
Also a patched TclXML package, needed for XML parsing in Tcl, is included.
This document targets the synchronization problem between two or more communicating entities, each having its own copy of the document. The specific application in mind is whiteboarding which is assumed to consist of a number of independent items, such as rectangles, paths, images etc. Each item has a state made up of its features, such as coordinates, colors, etc.
The task of this paper is to describe a method to achieve synchronization between two or more entities without any involvement of a third party. In addition, we show that no extra communication is needed to achive this. In
short, we describe a self-synchronization algorithm.
The application in mind is an XMPP network for transporting SVG graphics (Scalable Vector Graphics (SVG) 1.1 Specification, Mobile SVG Profiles: SVG Tiny and SVG Basic), but the analysis is not limited to this.
A few assumptions go into this discussion:
We will start with the simpler case of two interacting entities.
The state of a particular item is denoted S. An items state consists of all the attributes that describe it, such as coordinates, colors, strokes, fills etc.
The initial state of the item is S_0 and it can safely be assumed that it is identical at both A and B since the entity that creates it just transmits it to the other entity without any intervention.
Each item has a version attribute with an initial value of 0. The state with version i is denoted S_i.
Edit operations also carry a version attribute. Edits are denoted a, b, c,... and with version i they are a_i etc., or with numbers a1, b2, etc. It can be helpful to picture an edit operation in xml as,
<Edit(a) version='i' id='...' .../>
The state after an edit a1 will be S(a1), and after a sequence of edits, S(a1 b2 c3) etc.
Describe a timeline from left to right, for the entities A and B. See below.
S_0 S_1(a1) S_2(a1b2) A ---------------------------------------------------------------------- \ / \ / a1\ / \ / \ / \ / \ / \/ \ b2/ /\ \ / / \ B ---------------------------------------------------------------------- S_0 S_1(a1) S_2(a1b2) ---> time
Figure 1.
Edit operations are initiated either by A or B, and transported to the other entity, which is pictured by "/" or "\" lines. These are the "edit lines". Each edit line has an operator a_i etc., here indicated by a1 and b2.
In this figure it is important to distinguish between noncrossing sections and crossing sections. It is evident from the figure which is which. Noncrossing sections will never result in any synchronization problems since all edits will be applied in the same order at both A and B. Thus, only crossing sections need to be considered.
Edit operations, or edits, can be of two types:
Edits can either be:
Local edits are always trivially adopted. Remote edits can either be adopted or rejected. It is the task of this document to decide which cases to reject and how to change an items state after a rejection to achieve mutual
synchronization.
It is perfectly clear that perfect synchronization between two entities cannot be achieved at any time since travel time (think speed of light plus something) is larger than zero. We relax the task to achieve synchronization between the two entities after all edits from another entity have been received.
An edit operation is constructed locally by the entity that makes it. It always get a version attribute "one plus" the items version attribute, and the items version is incremented by one when the edit is applied.
Before an edit a:
S_2()
After:
S_3(a3)
and the edit is, of course, a3.
We can describe this formally as:
a_i+1 S_i(*) = S_i+1(* a_i+1)
where we have used * for all the (accepted) edits, if any, that have been applied to the item so far.
A remote edit will either be accepted or rejected. In any case the items versionattribute is incremented with one irrespective of the edits version number,
a_i S_j(*) = S_j+1(**)
where we have indicated the new state by ** which we will define below.
Lets start with the normal case with noncrossing sections, thus no conflicting edits. Picture it as:
S_0 S_1(a1) S_2(a1b2) A ---------------------------------------------------------------------- \ / a1\ / \ / \ / \ b2/ \ / B ---------------------------------------------------------------------- S_0 S_1(a1) S_2(a1b2)
Figure 2.
Local edits are always trivially accepted so we only need to describe the remote edits. In our case we get,
b_i+1 S_i(a_i) = S_i+1(a_i b_i+1)
that is, apply the edit and increment the version with one. However, in a more general case the edits may be denoted *,
b_i+1 S_i(*) = S_i+1(* b_i+1)
with the same interpretation as above. Thus, following an entities timeline, the items version number increases monotonically with one for each edit: 1, 2, 3,... This is true for any case, also for rejected edits. Important!
Remote edits that will be adopted will have an edit version which is exactly the items version plus one, that is,
b_i+1 S_i(*) = S_i+1(* b_i+1)
which is identical to a local edit. We can therefore make the likely hypothesis that remote edits with version not one plus the items number shall be rejected since they are "out of sync".
The remaining and most important question is to determine how the items edit state shall be changed when an edit is rejected. Lets start with the normal accepted states to see the patterns:
c3 S_2(a1 b2) = S_3(a1 b2 c3)
while a rejected case will look something like,
c2 S_2(a1 b2) = S_3(???)
where we will define the question marks below.
As an example, consider a state S_3(a1 b2 c3) with an incoming edit d1. Our hypothesis will be to undo all edits with version numbers larger or identical to the remote edits version number. Thus,
d1 S_3(a1 b2 c3) = S_4()
A few more cases to trace out the pattern:
d2 S_3(a1 b2 c3) = S_4(a1) d3 S_3(a1 b2 c3) = S_4(a1 b2)
to compare with the adopted case,
d4 S_3(a1 b2 c3) = S_4(a1 b2 c3 d4)
It may also happen that the edits version is larger than any of the items edit state numbers. In this case no change of the items state is made,
c3 S_3(a1) = S_4(a1)
If we put this in formal terms it reads,
a_i S_j(..., i-1, i, i+1,...,k) = S_j+1(..., i-1) for k >= i, i != j+1
where we have simplified the notation slightly. If i is larger than k we get,
a_i S_j(...,k) = S_j+1(...,k) for k < i, i != j+1
If we take the short description, a remote edit, a_i+1 S_j(q_k), with i != j and k > i will result in a new state S_j+1(q_i) where q_i is a previous edit state. If k <= i the edit state is unchanged.
Before presenting a formal evidence of this method, lets look into a few examples which will make the method plausible. Consider these cases and convince yourself of that the end states are identical despite conflicting edits. We
don't consider noncrossing sections unless to verify that we retain a synchronized state. We denote the initial state S_0 which is the same as S_0().
S_0 S_1(a1) S_2() A ---------------------------------------------------------------------- \ / a1\ / \ / \ / \ b1/ \ / \ B ---------------------------------------------------------------------- S_0 S_1(b1) S_2()
Figure 3.
S_2(a1b2) S_0 S_1(a1) S_3() S_4() A ---------------------------------------------------------------------- \ \ / / a1\ b2\ / / \ \------- / \ / \ / \ \ / / \ \ / / \ -----/ c1/ \ d3/\ / \ / \ B ---------------------------------------------------------------------- S_0 S_1(c1) S_2() S_4() S_3(d3)
Figure 4.
S_0 S_1(a1) S_2() S_3() S_4() S_5(e5) A ---------------------------------------------------------------------- \ / / / \ a1\ / / / e5\ \ / / / \ \ / / / \ \ / / \ / \ / / \ / --------------/ \ b1/ c2/ d3/\ \ / / / \ \ B ---------------------------------------------------------------------- S_0 S_1(b1) S_3(b1c2d3) S_5(e5) S_2(b1c2) S_4()
Figure 5.
In the above example we also added a nonconflicting edit to the right to verify that a new edit will be accepted.
S_2(a1b2) S_0 S_1(a1) S_3() S_4() A ---------------------------------------------------------------------- \ \ / / a1\ b2\ / / \ \ ---------- \ / \ / \ \/ / \ /\ / \/ ----------- c1/ d2/\ \ / / \ \ B ---------------------------------------------------------------------- S_0 S_1(c1) S_3() S_4() S_2(c1d2)
Figure 6.
It is evident from the examples above that a crossing section revokes all edits for both entities to their original state that they have before the crossing section. With an initial state S_0() we get the final state S_k() with k > 0.
Use the items version numbers to define a sequence for each entity. By definition all version numbers describe the sequence of natural numbers starting with 0. (Well, 0 is not a natural number but we add 0 to this set.) More precisely, the numbers describe the items version number it receives after the edit has been applied. The number at the edit lines initiator end is the edits version number.
0 1 2 3 4 5 6 7 A ---------------------------------------------------------------------- \ \ / \/ \ / \ / /\ \ / \/ \/ \ \ / /\ /\ \ \ / B ---------------------------------------------------------------------- 0 1 2 3 4 5 6 7
Figure 7.
Crossing lines will generate unequal numbers at each end of the edit line. Only edit lines with identical numbers at each end will be accepted by both entities. In the above case these are 6 and 7.
Note also that for the edit lines in the crossing section the initiator end will have a strictly lower number than the target end. The first and last edit of each entity in the crossing section must have at least one crossing by
definition. Any edits inbetween must have at least two crossings to "link together" the edits. The difference between an edits target number and its initiator number (its version) is identical to the number of crossings.
Prove that all crossings generate unequal version numbers, and noncrossing lines will give identical numbers.
From the figure it is evident that any noncrossing line (edit) have identical versions, and thus no conflicts. It is also evident that this is the only possibility to generate edits with identical versions.
QED
It must also be proven that both entities states after a crossing section are identical.
Consider, for instance, the entity A. It will make a local edit 1, and possibly zero or more edits after that, before receiving the edit from B, which will have version 1. In any case the receiving edit will be in conflict and thus rejected
since version numbers will not match. Also, all edits made (1, 2,..k ; k>=1) will be revoked taking it back to its original state S_0.
If we denote this slightly more formally as B's first edit a1, and A's state when receiving B's first edit will be S_k(q1,...,q_k) where k >= 1. The operation will be,
a1 S_k(q1,...,q_k) = S_k+1() with k >= 1
The a1 edit line will have 1 in its initiator end and k+1 at its target end,
1 --- k+1
It remains to be proven that any subsequent edits A receives will revoke any local edits made by A. By assumption none of B's edits will be adopted.
Assume that A makes zero or more edits before receiving B's next edit denoted b. If zero edits made there is nothing to prove. Assume therefore that A has made the local edits q_k+2,...,q_m, and its state is
S_m(q_k+2,...,q_m) with m >= k+2
The crucial question is the version of B's edit b. In particular we must know its highest version number possible since this gives the largest chance of A's edits to not be revoked.
By assumption it must cross A's last edit before receiving a1. This will give b its max version. Since A has made k edits and B one, its max version must be k+1. Apply the edit to A:
b_k+1 S_m(q_k+2, ..., q_m) = S_m+1()
since all higher edits than k+1 will be revoked. During this discussion it is helpful to consider figure 8 below.
k k+1 m m+1 0 1 2 3 4 5 A ---------------------------------------------------------------------- \ \ / \ / \ \/ / \ /\ / \ \/ \ / \ /\ \ / \ / \ \ \ / \ / \ \ B ---------------------------------------------------------------------- 0 1 2 3 4 5 k+2
Figure 8.
The reasoning above can now be applied to any subsequent edit A will receive from B without loss of generality. This will be described now.
Consider two consecutive edits at B, b and c, and A's edit just before it receives b from B, see figure 9. Give the edit a version k. This means that
k k+1 A ---------------------------------------------------------------------- a\ / \\\/ \/ / /\ / ... / \ / ... / \ / / \ b/ c/ \ B ---------------------------------------------------------------------- k+1 k+2
Figure 9.
the number of edits A has made, including a, plus the number of edits it has received from B, is equal to k. Consider now B when it receives edit a. It must have received all of A's edits up to and including a, as well of all B's
edits plus the two b and c. Thus the index is k+2. If we seek the max version of the edit c, that must be the nearest lower index, k+1. As above, it is the largest edit index which gives A's edits the highest chance to not be revoked.
Convince yourself of that any edits A has made before a, that are received by B after the edit c, will result in a lower edit number of c relative k+2. Assume now that A has made a number of edits after k+1, indicated by \\\ in the figure. This will make A's state just before receiving the edit c as,
S_m(q_k+2,q_k+3,...,q_m) with m >= k+2
Note that when the edit q_k+2 is applied, the state is identical to the initial state. It is now a simple matter to apply edit c as,
c_k+1 S_m(q_k+2,q_k+3,...,q_m) = S_m+1() with m >= k+2
All edits will be revoked once again.
Thus, A's state after the crossing section will be identical to its initial state at the start of the crossing section. By symmetry, the same will be true for entity B.
QED
Show that an edit line a from A that is being crossed by at least one edit from B will have its local edit revoked and its remote edit rejected.
Since its target end will have a number larger than its init end, the edit a at B will not be accepted.
By assumption there is at least one edit from B that crosses a. Assume that there are m >= 1 crosses of a, see figure 10. We have arbitrarily denoted a's version with k, and also denoted the first crossing edit with b. The last of
these edits that A will recive will have an index k+m+... where ... will be the number of local edits made after a but before k+m+...
k k+1 k+m+... A ---------------------------------------------------------------------- a\ / ... / \/ / /\ / ... / \ / ... / \/ / /\ b/ ... / \ B ---------------------------------------------------------------------- i k+m
Figure 10.
The edit a will have its target index k+m since there are m crossings. Denote the number of crossings of edit b in addition to the edit a with n, n >= 0. This is equal to the number of edits B will receive between its local edit b and
receiving edit a. Thus there are n+1 crossings of edit b. It is now a simple matter of arithmetic to find b's version number i,
i = (k+m) - m - n = k-n with n >= 0
or
i <= k
We can now apply edit b at A as,
b_i S_k(a_k) = S_k+1() since i <= k
Thus, also a's local edit will be revoked.
By symmetry this is valid for all edits that are being crossed, independently of A or B.
QED
(with Joonas Govenius)
It is important to consider seriality in this case, or in other words, edits are transported sequentially through a server. Consider figure 11 where we have shown two entities, A and B, between which an edit a takes place, and a third
arbitrary entity C. We may consider entity C to comprise all other entities not A or B because:
P1 A ----------o-------o---o---o------------------------------------------- / ... / a\ / / / / P2 B -------o-------o-------o------o--------------------------------------- / / / \ / / / / \/ ====*=======*=======*=======*========================================= / / / \ / ... / / \ C -o-------o-------o-------------o--------------------------------------
Figure 11.
We have symbolically shown the server, or sequencer, with ===. Each actual edit, local or remote, are indicated with -o-. Sequencing implies that the number of C's edits that reach A before P1 is smaller or equal to the number of its edits that reaches B before P2. Thus, an edit a between two entitites divides the edits from a third entity into two sets.
Edit a is any edit from A that is being crossed by one or more edits from B. We denote the first edit of B that crosses a with b. The formal proof makes use of the following notations and figure 12 below.
Notations:
Points: P1 is where edit a is made by A P2 is where edit b is made by B P3 is where edit a is received by B P4 is where edit b is received by A A: The edits up to and including P1: kA is the number of local edits made by A, a included kB is the number of edits received from B kC is the number of edits received from C B: m is the number of B's edits that cross edit a, with b being the first one; m > 0 n+1 is the number of A's edits that cross b, edit a included; n >= 0 p is the number of C's edits received by B up to P3 r is the number of C's edits received by B up to P2 i is the unknown version (index) of edit b
(P4) (P1) kA+kB+kC+1 kA+kB+kC | A -----o-----o-o-----o--o--------o-----o-------------------------------- / kC / \ n \ \ / / / ... / \ ... \ a\ / m / \ / ... / \/ / /\ / ... / \ / ... / \/ b/ /\ / ... / \ B ------o------------o-o-----o--o-o------------------------------------- / r / i / kA+kB+m+p / ... / (P2) / (P3) / p / / ... / C -o-----------------------o-------------------------------------------- ... \ \ \ \ \ \ \ ... R ----------------------------------------------------------------------
Figure 12.
A few notes on the indices of figure 12. At P1 the index is kA+kB+kC by our definitions. At P3 we have received exactly kA edits from A, and the kB of B's edits received by A at P1 must be added with B's local edits not yet received
by A, which we have denoted m. In addition, B has received p edits from C. This makes kA+kB+m+p.
We now need to prove that edit a is revoked locally and rejected remotely.
If we impose seriality on edit a we get
kC <= p, or kC-p <= 0.
The condition for edit a to be accepted by B is,
kA+kB+kC = kA+kB+m+p
or
kC = m+p with m > 0
or
kC-p = m with m > 0
but this is inconsistent with the seriality condition above. Thus, any edit that crosses any other edit line will be rejected remotely.
We also need to prove that edit a will be revoked locally by edit b. The edit b's version number i is,
i = (kB+1) + (kA - (n+1)) + r = kA+kB+r-n, with n >= 0
if we add the local edits, edits from A, and edits from C. If we impose seriality on edit b we get r <= kC since by assumption b is the first edit A receives after P1, and thus no edits from C between P1 and P4.
To revoke edit a locally we require,
i <= kA+kB+kC
or
kB+kA+r-n <= kA+kB+kC
which is simplified to,
r-kC <= n, with n >= 0
By the seriality condition, r <= kC, or, r-kC <= 0, this is always true.
QED
It now remains to be proven that an entity R that makes no local edits will be consistent with any other entity. In particular, we need to prove that any edits between two other entities that cross will be revoked or rejected by R.
Consider figure 13 below where we have added the servers (sequencers) timeline in addition to A, B, C, and R. Let b be any edit made by B, and a an edit by A that crosses b, not necessarily the first crossing of b, but we make sure that A generates the first edit that crosses b. We denote edit u the last edit R receives before edit a. If edit a is the first edit that crosses b then edit u is identical to edit b.
k P1 A ----------------o------------o----------------------------------------- /\a / / \ / / \ / / \ / B -------------/--o--------------o---------------------------------------- / \b \/ / / \ /\ / / \ / \ / / \/ \/P5 ========*============*==*==*============================================ P2 P3 P4\ \ \ \ C ........................................................................ \ \ \ \ R ------------------------------o--o-------------------------------------- P6 u
Figure 13.
Note that the line P2->P1 is only a guideline. Any edits from B or C at P1 must have passed the server before P2.
There are two logical possibilities for a and b to cross; P3 < P5 or P5 < P3. Lets start by considering P3 < P5 as indicated in the figure. In this case we get in addition P3 <= P4 by assumption. We define the number of edits at P1 and P6 as
k = kA+kB+kC u = uA+uB+uC
where the indices A, B, and C, indicate the origin of these edits. Since u is defined to be the last edit R receives before receiving edit a, we have
kA = uA+1
Since a and b cross we have P2 < P3. Therefore we get (with P3 <= P4),
kB+kC <= uB+uC-1
or
kB+kC+1 <= uB+uC
where the 1 comes from edit b. We now get,
k = kA+kB+kC = uA+1+kB+kC <= uA+uB+uC = u
or
k <= u
Thus, edit a will be rejected by R and edit u will be revoked. Note that this is true for edits coming from any entity that crosses b. This will also be true when a is the first edit to cross b, and thus edit b is identical to edit u and will therefore be revoked.
The other case where P5 < P3, and edit a reaches the server before edit b, follows directly from the above case if we just switch A <-> B and a <-> b using the symmetry.
QED
It may be possible to relax the assumption that all operations are noncommutative. The algorithmic complexity increases and it will probably be necessary that all implementations agree on an edit matrix of operations where each entry describes if any two edits commute or not.
Mats Bengtsson (June, 2006)
(parts with Joonas Govenius)
If you want to run Coccinella on a machine architecture not presently supported (MacOSX/Windows/Linux-x86/NetBSD) there are two extensions to Tcl/Tk itself which you need to build from their C sources. These are:
They are built the usual way using configure/make/make install but I'm unsure if you need to have Tcl/Tk sources available. This is under the assumption you are running Tcl/Tk 8.5 or later. This will be required before Coccinella version 0.96.10. Then you just get Coccinella sources and execute it from the console (./Coccinella.tcl).