/// <summary> /// Merge clocks /// </summary> public VectorClock Merge(VectorClock clock) { int i = 0; int j = 0; var versions = Versions.ToArray(); var clockVersions = clock.Versions.ToArray(); var newClockVersions = List.empty <ClockEntry>(); while (i < versions.Length && j < clockVersions.Length) { var v1 = versions[i]; var v2 = clockVersions[j]; if (v1.NodeId == v2.NodeId) { var nc = new ClockEntry(v1.NodeId, (int)Math.Max(v1.Version, v2.Version)); newClockVersions = newClockVersions.Add(nc); i++; j++; } else if (v1.NodeId < v2.NodeId) { newClockVersions = newClockVersions.Add(v1); i++; } else { newClockVersions = newClockVersions.Add(v2); j++; } } // Okay now there may be leftovers on one or the other list remaining for (int k = i; k < versions.Length; k++) { newClockVersions = newClockVersions.Add(versions[k]); } for (int k = j; k < clockVersions.Length; k++) { newClockVersions = newClockVersions.Add(clockVersions[k]); } return(new VectorClock(newClockVersions)); }
/// <summary> /// <para> /// Is this reflexive, antisymetic, and transitive? Compare two VectorClocks, /// the outcomes will be one of the following: /// </para> /// <para> /// * Clock 1 is /before/ clock 2 /// if there exists an i such that c1(i) <= c(2) and there does not /// exist a j such that c1(j) > c2(j). /// </para> /// <para> /// * Clock 1 is /concurrent/ to clock 2 if there exists an i, j such that /// c1(i) < c2(i) and c1(j) > c2(j) /// </para> /// <para> /// * Clock 1 is /after/ clock 2 otherwise /// </para> /// </summary> /// <param name="v1">The first VectorClock</param> /// <param name="v2">The second VectorClock</param> /// <returns>Whether the change occured before, after or concurrently</returns> public static Occured Compare(VectorClock v1, VectorClock v2) { if (v1 == null || v2 == null) { throw new ArgumentException("Can't compare null vector clocks!"); } // We do two checks: v1 <= v2 and v2 <= v1 if both are true then bool v1Bigger = false; bool v2Bigger = false; int p1 = 0; int p2 = 0; while (p1 < v1.Versions.Count && p2 < v2.Versions.Count) { ClockEntry ver1 = v1.Versions[p1]; ClockEntry ver2 = v2.Versions[p2]; if (ver1.NodeId == ver2.NodeId) { if (ver1.Version > ver2.Version) { v1Bigger = true; } else if (ver2.Version > ver1.Version) { v2Bigger = true; } p1++; p2++; } else if (ver1.NodeId > ver2.NodeId) { // since ver1 is bigger that means it is missing a version that ver2 has v2Bigger = true; p2++; } else { // this means ver2 is bigger which means it is missing a version ver1 has v1Bigger = true; p1++; } } // Check for left overs if (p1 < v1.Versions.Count) { v1Bigger = true; } else if (p2 < v2.Versions.Count) { v2Bigger = true; } // This is the case where they are equal, return BEFORE arbitrarily if (!v1Bigger && !v2Bigger) { return(Occured.Before); } // This is the case where v1 is a successor clock to v2 else if (v1Bigger && !v2Bigger) { return(Occured.After); } // This is the case where v2 is a successor clock to v1 else if (!v1Bigger && v2Bigger) { return(Occured.Before); } // This is the case where both clocks are parallel to one another else { return(Occured.Concurrently); } }