mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-26 23:46:36 +00:00
fixed remove leaderboard operational transformation
This commit is contained in:
+10
-4
@@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
@@ -19,6 +20,7 @@ import java.util.concurrent.Executors;
|
||||
* @param <S> type of state managed by this server to which the operations can be applied
|
||||
*/
|
||||
public class PeerImpl<O extends Operation<S>, S> implements Peer<O, S> {
|
||||
private static final Logger logger = Logger.getLogger(PeerImpl.class.getName());
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -42,20 +44,20 @@ public class PeerImpl<O extends Operation<S>, S> implements Peer<O, S> {
|
||||
* confirmed, the first operation from the queue is removed because operations sent
|
||||
* from this peer to the remote peer are processed in order.
|
||||
*/
|
||||
private Map<Peer<O, S>, UnmergedOperationsQueue<O, S>> unmergedOperationsForPeer = new HashMap<Peer<O, S>, UnmergedOperationsQueue<O, S>>();
|
||||
private final Map<Peer<O, S>, UnmergedOperationsQueue<O, S>> unmergedOperationsForPeer = new HashMap<Peer<O, S>, UnmergedOperationsQueue<O, S>>();
|
||||
|
||||
/**
|
||||
* Remembers per peer how many of that peer's operations this peer has already
|
||||
* applied locally.
|
||||
*/
|
||||
private Map<Peer<O, S>, Integer> numberOfMergedOperations = new HashMap<Peer<O, S>, Integer>();
|
||||
private final Map<Peer<O, S>, Integer> numberOfMergedOperations = new HashMap<Peer<O, S>, Integer>();
|
||||
|
||||
private Transformer<O> transformer;
|
||||
private final Transformer<O> transformer;
|
||||
|
||||
/**
|
||||
* The background task handler which sends out the asynchronous updates to the peers.
|
||||
*/
|
||||
private ExecutorService merger;
|
||||
private final ExecutorService merger;
|
||||
|
||||
public PeerImpl(Transformer<O> transformer, S initialState, Role role) {
|
||||
this.transformer = transformer;
|
||||
@@ -234,6 +236,7 @@ public class PeerImpl<O extends Operation<S>, S> implements Peer<O, S> {
|
||||
}
|
||||
|
||||
private void taskScheduled() {
|
||||
logger.fine(""+this+" taskScheduled incrementing scheduleOrRunning from "+scheduledOrRunning+" to "+(scheduledOrRunning+1));
|
||||
scheduledOrRunning++;
|
||||
}
|
||||
|
||||
@@ -242,8 +245,10 @@ public class PeerImpl<O extends Operation<S>, S> implements Peer<O, S> {
|
||||
* Unblocks {@link #waitForNotRunning()} if the merger's queue got empty by this.
|
||||
*/
|
||||
private synchronized void taskFinished() {
|
||||
logger.fine(""+this+" taskFinished decrementing scheduleOrRunning from "+scheduledOrRunning+" to "+(scheduledOrRunning-1));
|
||||
scheduledOrRunning--;
|
||||
if (scheduledOrRunning == 0) {
|
||||
logger.fine(""+this+" taskFinished notifying waiters");
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
@@ -253,6 +258,7 @@ public class PeerImpl<O extends Operation<S>, S> implements Peer<O, S> {
|
||||
while (scheduledOrRunning > 0) {
|
||||
try {
|
||||
wait();
|
||||
logger.fine(""+this+" waitForNotRunning scheduleOrRunning: "+scheduledOrRunning);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore interruption, try again
|
||||
}
|
||||
|
||||
+2
-2
@@ -59,14 +59,14 @@ public class OperationalTransformationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddColumnToLeaderboardOnClientAndRemoveLeaderboardOnServer() {
|
||||
public void testAddColumnToLeaderboardOnClientAndRemoveLeaderboardOnServer() throws InterruptedException {
|
||||
RacingEventServiceOperation addLeaderboardColumn = new AddColumnToLeaderboard(
|
||||
"newColumn", DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME, /* medalRace */ true);
|
||||
server.apply(addLeaderboardColumn);
|
||||
RacingEventServiceOperation removeDefaultLeaderboard = new RemoveLeaderboard(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME);
|
||||
replica.apply(removeDefaultLeaderboard);
|
||||
server.waitForNotRunning();
|
||||
replica.waitForNotRunning();
|
||||
server.waitForNotRunning();
|
||||
assertEquals(0, racingEventServiceReplica.getLeaderboards().size());
|
||||
assertEquals(0, racingEventServiceServer.getLeaderboards().size());
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ public abstract class AbstractLeaderboardColumnOperation extends AbstractLeaderb
|
||||
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerRemoveColumnFromLeaderboard(
|
||||
public RacingEventServiceOperation transformRemoveColumnFromLeaderboardServerOp(
|
||||
RemoveColumnFromLeaderboard removeColumnFromLeaderboardServerOp) {
|
||||
if (affectsSameColumn(removeColumnFromLeaderboardServerOp)) {
|
||||
// skip server's remove and hence only apply the client's remove operation
|
||||
@@ -31,7 +31,7 @@ public abstract class AbstractLeaderboardColumnOperation extends AbstractLeaderb
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientRemoveColumnFromLeaderboard(
|
||||
public RacingEventServiceOperation transformRemoveColumnFromLeaderboardClientOp(
|
||||
RemoveColumnFromLeaderboard removeColumnFromLeaderboardClientOp) {
|
||||
if (affectsSameColumn(removeColumnFromLeaderboardClientOp)) {
|
||||
// skip client's remove and hence only apply the server's remove operation
|
||||
|
||||
-19
@@ -18,23 +18,4 @@ public abstract class AbstractLeaderboardOperation extends AbstractRacingEventSe
|
||||
return getLeaderboardName().equals(other.getLeaderboardName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRemoveLeaderboardClientOp(RemoveLeaderboard removeLeaderboard) {
|
||||
if (affectsSameLeaderboard(removeLeaderboard)) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRemoveLeaderboardServerOp(RemoveLeaderboard removeLeaderboard) {
|
||||
if (affectsSameLeaderboard(removeLeaderboard)) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-6
@@ -33,27 +33,39 @@ public abstract class AbstractRacingEventServiceOperation implements RacingEvent
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientRenameLeaderboardColumnOp(
|
||||
public RacingEventServiceOperation transformRenameLeaderboardColumnClientOp(
|
||||
RenameLeaderboardColumn renameLeaderboardColumnClientOp) {
|
||||
return renameLeaderboardColumnClientOp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerRenameLeaderboardColumnOp(
|
||||
public RacingEventServiceOperation transformRenameLeaderboardColumnServerOp(
|
||||
RenameLeaderboardColumn renameLeaderboardColumnServerOp) {
|
||||
return renameLeaderboardColumnServerOp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerRemoveColumnFromLeaderboard(RemoveColumnFromLeaderboard removeColumnFromLeaderboardServerOp) {
|
||||
public RacingEventServiceOperation transformRemoveColumnFromLeaderboardServerOp(RemoveColumnFromLeaderboard removeColumnFromLeaderboardServerOp) {
|
||||
return removeColumnFromLeaderboardServerOp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientRemoveColumnFromLeaderboard(RemoveColumnFromLeaderboard removeColumnFromLeaderboardClientOp) {
|
||||
public RacingEventServiceOperation transformRemoveColumnFromLeaderboardClientOp(RemoveColumnFromLeaderboard removeColumnFromLeaderboardClientOp) {
|
||||
return removeColumnFromLeaderboardClientOp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformAddColumnToLeaderboardClientOp(
|
||||
AddColumnToLeaderboard addColumnToLeaderboard) {
|
||||
return addColumnToLeaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformAddColumnToLeaderboardServerOp(
|
||||
AddColumnToLeaderboard addColumnToLeaderboard) {
|
||||
return addColumnToLeaderboard;
|
||||
}
|
||||
|
||||
public static RacingEventServiceOperation getNoOp() {
|
||||
return new AbstractRacingEventServiceOperation() {
|
||||
@Override
|
||||
@@ -63,12 +75,17 @@ public abstract class AbstractRacingEventServiceOperation implements RacingEvent
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) {
|
||||
return serverOp;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) {
|
||||
return clientOp;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "noop";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+2
-4
@@ -25,13 +25,11 @@ public class AddColumnToLeaderboard extends AbstractLeaderboardColumnOperation {
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
return serverOp.transformAddColumnToLeaderboardClientOp(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
return clientOp.transformAddColumnToLeaderboardServerOp(this);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -29,13 +29,13 @@ public interface RacingEventServiceOperation extends Operation<RacingEventServic
|
||||
* operation deals with the leaderboard column being removed by <code>removeColumnFromLeaderboardClientOp</code>,
|
||||
* the result will be <code>null</code>, meaning that this operation cannot be applied after the column has been removed.
|
||||
*/
|
||||
RacingEventServiceOperation transformClientRemoveColumnFromLeaderboard(RemoveColumnFromLeaderboard removeColumnFromLeaderboardClientOp);
|
||||
RacingEventServiceOperation transformRemoveColumnFromLeaderboardClientOp(RemoveColumnFromLeaderboard removeColumnFromLeaderboardClientOp);
|
||||
|
||||
RacingEventServiceOperation transformServerRemoveColumnFromLeaderboard(RemoveColumnFromLeaderboard removeColumnFromLeaderboardServerOp);
|
||||
RacingEventServiceOperation transformRemoveColumnFromLeaderboardServerOp(RemoveColumnFromLeaderboard removeColumnFromLeaderboardServerOp);
|
||||
|
||||
RacingEventServiceOperation transformClientRenameLeaderboardColumnOp(RenameLeaderboardColumn renameLeaderboardColumnClientOp);
|
||||
RacingEventServiceOperation transformRenameLeaderboardColumnClientOp(RenameLeaderboardColumn renameLeaderboardColumnClientOp);
|
||||
|
||||
RacingEventServiceOperation transformServerRenameLeaderboardColumnOp(RenameLeaderboardColumn renameLeaderboardColumnServerOp);
|
||||
RacingEventServiceOperation transformRenameLeaderboardColumnServerOp(RenameLeaderboardColumn renameLeaderboardColumnServerOp);
|
||||
|
||||
RacingEventServiceOperation transformAddLeaderboardClientOp(AddLeaderboard addLeaderboard);
|
||||
|
||||
@@ -44,4 +44,8 @@ public interface RacingEventServiceOperation extends Operation<RacingEventServic
|
||||
RacingEventServiceOperation transformRemoveLeaderboardClientOp(RemoveLeaderboard removeLeaderboard);
|
||||
|
||||
RacingEventServiceOperation transformRemoveLeaderboardServerOp(RemoveLeaderboard removeLeaderboard);
|
||||
|
||||
RacingEventServiceOperation transformAddColumnToLeaderboardClientOp(AddColumnToLeaderboard addColumnToLeaderboard);
|
||||
|
||||
RacingEventServiceOperation transformAddColumnToLeaderboardServerOp(AddColumnToLeaderboard addColumnToLeaderboard);
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,12 +17,12 @@ public class RemoveColumnFromLeaderboard extends AbstractLeaderboardColumnOperat
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) {
|
||||
return serverOp.transformClientRemoveColumnFromLeaderboard(this);
|
||||
return serverOp.transformRemoveColumnFromLeaderboardClientOp(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) {
|
||||
return clientOp.transformServerRemoveColumnFromLeaderboard(this);
|
||||
return clientOp.transformRemoveColumnFromLeaderboardServerOp(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+55
@@ -23,4 +23,59 @@ public class RemoveLeaderboard extends AbstractLeaderboardOperation {
|
||||
return toState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRenameLeaderboardColumnClientOp(
|
||||
RenameLeaderboardColumn renameLeaderboardColumnClientOp) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRenameLeaderboardColumnServerOp(
|
||||
RenameLeaderboardColumn renameLeaderboardColumnServerOp) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRemoveColumnFromLeaderboardServerOp(
|
||||
RemoveColumnFromLeaderboard removeColumnFromLeaderboardServerOp) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRemoveColumnFromLeaderboardClientOp(
|
||||
RemoveColumnFromLeaderboard removeColumnFromLeaderboardClientOp) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformAddColumnToLeaderboardClientOp(
|
||||
AddColumnToLeaderboard addColumnToLeaderboard) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformAddColumnToLeaderboardServerOp(
|
||||
AddColumnToLeaderboard addColumnToLeaderboard) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRemoveLeaderboardClientOp(RemoveLeaderboard removeLeaderboard) {
|
||||
if (affectsSameLeaderboard(removeLeaderboard)) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformRemoveLeaderboardServerOp(RemoveLeaderboard removeLeaderboard) {
|
||||
if (affectsSameLeaderboard(removeLeaderboard)) {
|
||||
return AbstractRacingEventServiceOperation.getNoOp();
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,13 +19,13 @@ public class RenameLeaderboardColumn extends AbstractLeaderboardColumnOperation
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) {
|
||||
return serverOp.transformClientRenameLeaderboardColumnOp(this);
|
||||
return serverOp.transformRenameLeaderboardColumnClientOp(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) {
|
||||
return clientOp.transformServerRenameLeaderboardColumnOp(this);
|
||||
return clientOp.transformRenameLeaderboardColumnServerOp(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user