summaryrefslogtreecommitdiff
path: root/same/src/main/java
diff options
context:
space:
mode:
authorKjetil Ørbekk <kjetil.orbekk@gmail.com>2012-03-20 12:45:26 +0100
committerKjetil Ørbekk <kjetil.orbekk@gmail.com>2012-03-20 12:45:35 +0100
commit409dfe838e8ae30e2512256852c1fef31f3255b4 (patch)
tree002c0011d3549fb0da3ec3067e8376c84151a947 /same/src/main/java
parent6299172d3b9ba0b98b77583c0c3c5fc90d1b7db5 (diff)
Make sure there is only one valid new master.
This is done using the paxos proposal number as a certificate.
Diffstat (limited to 'same/src/main/java')
-rw-r--r--same/src/main/java/com/orbekk/paxos/MasterProposer.java4
-rw-r--r--same/src/main/java/com/orbekk/same/Client.java17
2 files changed, 14 insertions, 7 deletions
diff --git a/same/src/main/java/com/orbekk/paxos/MasterProposer.java b/same/src/main/java/com/orbekk/paxos/MasterProposer.java
index 8469cf4..094a749 100644
--- a/same/src/main/java/com/orbekk/paxos/MasterProposer.java
+++ b/same/src/main/java/com/orbekk/paxos/MasterProposer.java
@@ -91,9 +91,9 @@ public class MasterProposer extends Thread {
}
Integer proposeRetry(int proposalNumber, Runnable retryAction) {
- assert proposalNumber >= 0;
+ assert proposalNumber > 0;
int nextProposal = proposalNumber;
- int result = -1;
+ int result = nextProposal - 1;
while (!Thread.interrupted() && result != nextProposal) {
result = internalPropose(nextProposal);
diff --git a/same/src/main/java/com/orbekk/same/Client.java b/same/src/main/java/com/orbekk/same/Client.java
index 18fecd2..ceacd12 100644
--- a/same/src/main/java/com/orbekk/same/Client.java
+++ b/same/src/main/java/com/orbekk/same/Client.java
@@ -123,7 +123,7 @@ public class Client implements DiscoveryListener {
}
@Override
- public void masterTakeover(String masterUrl, String networkName,
+ public synchronized void masterTakeover(String masterUrl, String networkName,
int masterId) throws Exception {
if (masterId <= Client.this.masterId) {
logger.warn("{}:{} tried to take over, but current master is " +
@@ -135,6 +135,7 @@ public class Client implements DiscoveryListener {
new Object[]{masterUrl, networkName, masterId});
abortMasterElection();
Client.this.masterUrl = masterUrl;
+ Client.this.masterId = masterId;
connectionState = ConnectionState.STABLE;
}
@@ -147,7 +148,7 @@ public class Client implements DiscoveryListener {
}
logger.warn("Master down.");
connectionState = ConnectionState.UNSTABLE;
- tryBecomeMaster();
+ tryBecomeMaster(masterId);
}
};
@@ -266,7 +267,7 @@ public class Client implements DiscoveryListener {
return paxosUrls;
}
- private void tryBecomeMaster() {
+ private void tryBecomeMaster(int failedMasterId) {
List<String> paxosUrls = getPaxosUrls();
MasterProposer proposer = new MasterProposer(getUrl(), paxosUrls,
connections);
@@ -283,7 +284,12 @@ public class Client implements DiscoveryListener {
}
};
synchronized (this) {
- currentMasterProposal = proposer.startProposalTask(1, sleeperTask);
+ if (failedMasterId < masterId) {
+ logger.info("Master election aborted. Master already chosen.");
+ return;
+ }
+ currentMasterProposal = proposer.startProposalTask(masterId + 1,
+ sleeperTask);
}
Integer result = null;
try {
@@ -310,11 +316,12 @@ public class Client implements DiscoveryListener {
public void startMasterElection() {
List<String> participants = state.getList(".participants");
+ final int masterId = getMasterIdEstimate();
broadcaster.broadcast(participants, new ServiceOperation() {
@Override public void run(String url) {
ClientService client = connections.getClient(url);
try {
- client.masterDown(getMasterIdEstimate());
+ client.masterDown(masterId);
} catch (Exception e) {
logger.info("{}.masterDown() did not respond (ignored): " +
url, e);