Сортировочный список векторных часов (общий порядок)?
Я понимаю, что векторные часы обеспечивают только частичный порядок. Таким образом, вы не можете напрямую их отсортировать. По этой причине вы используете разделитель для векторов, которые являются параллельными, что приводит к общему порядку.
Однако сортировка векторных часов так, чтобы каждая причина предшествовала каждому эффекту в результирующем списке, похоже, не работает, и я не совсем понимаю, почему.
У меня есть обширные тесты, которые показывают, что сравнение двух векторов работает:
@Override
public int compareTo(VectorClock<K> that) {
var res = 0;
if (this.isAfter(that))
res = 1;
else if (that.isAfter(this))
res = -1;
else
res = this.timestamp.compareTo(that.timestamp);
System.out.println("compare " + this + " : " + that + " => " + res);
return res;
}
public boolean isAfter(VectorClock<K> that) {
boolean anyClockGreater = false;
var set = new HashSet<K>();
set.addAll(this.keySet());
set.addAll(that.keySet());
for (K key : set) {
final Clock thatClock = that.get(key);
final Clock thisClock = this.get(key);
if (thisClock == null || thisClock.isBefore(thatClock)) {
return false;
} else if (thisClock.isAfter(thatClock)) {
anyClockGreater = true;
}
}
// there is at least one local timestamp greater or local vector clock has additional timestamps
return anyClockGreater || that.entrySet().size() < entrySet().size();
}
Однако при сортировке списка векторных часов, например, одного с двумя векторами, которые имеют отношение случившегося до, и третьего вектора, который является параллельным обоим другим, может случиться так, что только параллельный вектор сравнивается с двумя другими, а векторы, которые зависят от друг на друга не сравниваются. Вместо этого их порядок (ошибочно) транзитивно определяется тай-брейком:
VectorClock<String> v1 = VectorClock.fromString("{0=23, 1=28, 2=15, 3=23, 4=15, 5=22, 6=14, 7=19}"); // after v3
VectorClock<String> v2 = VectorClock.fromString("{0=11, 1=16, 2=28, 3=17, 4=24, 5=15, 6=10, 7=8}");
VectorClock<String> v3 = VectorClock.fromString("{0=15, 1=19, 2=15, 3=20, 4=15, 5=22, 6=14, 7=19}"); // before v1
var s = new ArrayList<>(List.of(v1, v2, v3));
s.sort(VectorClock::compareTo);
assertTrue(s.indexOf(v3) < s.indexOf(v1));
Печатает (и терпит неудачу):
compare {0=11, 1=16, 2=28, 3=17, 4=24, 5=15, 6=10, 7=8} : {0=23, 1=28, 2=15, 3=23, 4=15, 5=22, 6=14, 7=19} => 1
compare {0=15, 1=19, 2=15, 3=20, 4=15, 5=22, 6=14, 7=19} : {0=11, 1=16, 2=28, 3=17, 4=24, 5=15, 6=10, 7=8} => 1
В чем основная причина этого? Это вообще невозможно или есть ошибка?