started making paxos more nack registant
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Andre Henriques 2024-01-08 15:52:49 +00:00
parent fbcd7542fc
commit 249a6e1ae3
3 changed files with 87 additions and 57 deletions

View File

@ -56,7 +56,7 @@ defmodule EventualLeaderElector do
{:timeout} -> {:timeout} ->
state = state =
if MapSet.size(state.heard_back) == 0 do if MapSet.size(state.heard_back) < floor(length(state.processes)/2) + 1 do
state state
else else
to_trust = Enum.at(Enum.sort(MapSet.to_list(state.heard_back)), 0) to_trust = Enum.at(Enum.sort(MapSet.to_list(state.heard_back)), 0)

View File

@ -42,6 +42,7 @@ defmodule Paxos do
pid_to_inform: pid_to_inform, pid_to_inform: pid_to_inform,
has_sent_accept: false, has_sent_accept: false,
action: action, action: action,
has_sent_prepare: false,
}) })
%{state | instmap: instmap} %{state | instmap: instmap}
@ -146,7 +147,7 @@ defmodule Paxos do
} end) } end)
true -> true ->
Utils.unicast({:nack, inst, ballot}, proc) Utils.unicast({:nack, inst, ballot, state.instmap[inst].ballot}, proc)
state state
end end
@ -157,8 +158,8 @@ defmodule Paxos do
state state
{:nack, inst, ballot} -> {:nack, inst, ballot, new_ballot} ->
IO.puts("#{state.name} - nack #{inspect(inst)} #{inspect(ballot)}") IO.puts("#{state.name} - nack #{inspect(inst)} #{inspect(ballot)} #{inspect(new_ballot)}")
cond do cond do
has_finished(state, inst) -> has_finished(state, inst) ->
@ -169,14 +170,35 @@ defmodule Paxos do
send(state.instmap[inst].pid_to_inform, {:abort, inst}) send(state.instmap[inst].pid_to_inform, {:abort, inst})
end end
EagerReliableBroadcast.broadcast(state.name, {:abort, inst, ballot, new_ballot})
set_instmap(state, inst, fn map -> %{ set_instmap(state, inst, fn map -> %{
map | has_sent_accept: false map | has_sent_accept: false,
ballot: new_ballot + 1,
has_sent_prepare: false,
} end) } end)
true -> true ->
state state
end end
{:rb_deliver, _proc, {:abort, inst, ballot}} ->
cond do
has_finished(state, inst) ->
state
state.instmap[inst].ballot == ballot ->
if Map.has_key?(state.instmap, inst) and state.instmap[inst].pid_to_inform != nil do
send(state.instmap[inst].pid_to_inform, {:abort, inst})
end
state
true ->
state
end
{:prepared, inst, ballot, accepted_ballot, accepted_value} -> {:prepared, inst, ballot, accepted_ballot, accepted_value} ->
IO.puts( IO.puts(
"#{state.name} - prepared #{inspect(inst)} #{inspect(ballot)} #{inspect(accepted_ballot)} #{inspect(accepted_value)}" "#{state.name} - prepared #{inspect(inst)} #{inspect(ballot)} #{inspect(accepted_ballot)} #{inspect(accepted_value)}"
@ -225,7 +247,7 @@ defmodule Paxos do
} end) } end)
else else
IO.puts("#{state.name} -> #{proc} nack") IO.puts("#{state.name} -> #{proc} nack")
Utils.unicast({:nack, inst, ballot}, proc) Utils.unicast({:nack, inst, ballot, state.instmap[inst].ballot}, proc)
state state
end end
end end
@ -233,10 +255,11 @@ defmodule Paxos do
{:accepted, inst, ballot} -> {:accepted, inst, ballot} ->
IO.puts("#{state.name} accepted #{inspect(inst)} #{inspect(ballot)}") IO.puts("#{state.name} accepted #{inspect(inst)} #{inspect(ballot)}")
if has_finished(state, inst) do cond do
has_finished(state, inst) ->
state state
else
if state.leader == state.name and state.instmap[inst].ballot == ballot do state.leader == state.name and state.instmap[inst].ballot == ballot ->
accepted( accepted(
set_instmap(state, inst, fn map -> %{ set_instmap(state, inst, fn map -> %{
map map
@ -244,10 +267,10 @@ defmodule Paxos do
} end), } end),
inst inst
) )
else
true ->
state state
end end
end
{:get_value, inst, pid_to_inform, t} -> {:get_value, inst, pid_to_inform, t} ->
# IO.puts("#{state.name} get_value") # IO.puts("#{state.name} get_value")
@ -302,6 +325,9 @@ defmodule Paxos do
Map.get(state.instmap, inst) == nil and Map.get(state.other_values, inst) == nil -> Map.get(state.instmap, inst) == nil and Map.get(state.other_values, inst) == nil ->
state state
Map.get(state.instmap, inst) != nil and state.instmap[inst].has_sent_prepare ->
state
Map.get(state.instmap, inst) != nil and state.instmap[inst].has_sent_accept -> Map.get(state.instmap, inst) != nil and state.instmap[inst].has_sent_accept ->
state state
@ -315,6 +341,7 @@ defmodule Paxos do
| prepared_values: [], | prepared_values: [],
accepted: 0, accepted: 0,
ballot_value: nil, ballot_value: nil,
has_sent_prepare: true,
has_sent_accept: false has_sent_accept: false
} end) } end)
end end
@ -330,10 +357,13 @@ defmodule Paxos do
not state.instmap[inst].has_sent_accept do not state.instmap[inst].has_sent_accept do
{_, a_val} = {_, a_val} =
Enum.reduce(state.instmap[inst].prepared_values, {0, nil}, fn {bal, val}, Enum.reduce(state.instmap[inst].prepared_values, {0, nil}, fn {bal, val},
{a_bal, a_val} -> {acc_bal, acc_val} ->
if a_bal > bal do cond do
{a_bal, a_val} val == nil ->
else {acc_bal, acc_val}
acc_bal > bal ->
{acc_bal, acc_val}
true ->
{bal, val} {bal, val}
end end
end) end)

View File

@ -22,42 +22,42 @@ test_suite = [
# Use TestUtil.get_local_config(n) to generate a single-node configuration # Use TestUtil.get_local_config(n) to generate a single-node configuration
# consisting of n processes, all running on the same node. # consisting of n processes, all running on the same node.
# {&PaxosTest.run_simple/3, TestUtil.get_local_config(3), 10, {&PaxosTest.run_simple/3, TestUtil.get_local_config(3), 10,
# "No failures, no concurrent ballots, 3 local procs"}, "No failures, no concurrent ballots, 3 local procs"},
# {&PaxosTest.run_simple/3, TestUtil.get_dist_config(host, 3), 10, {&PaxosTest.run_simple/3, TestUtil.get_dist_config(host, 3), 10,
# "No failures, no concurrent ballots, 3 nodes"}, "No failures, no concurrent ballots, 3 nodes"},
# {&PaxosTest.run_simple/3, TestUtil.get_local_config(5), 10, {&PaxosTest.run_simple/3, TestUtil.get_local_config(5), 10,
# "No failures, no concurrent ballots, 5 local procs"}, "No failures, no concurrent ballots, 5 local procs"},
# {&PaxosTest.run_simple_2/3, TestUtil.get_dist_config(host, 3), 10, {&PaxosTest.run_simple_2/3, TestUtil.get_dist_config(host, 3), 10,
# "No failures, 2 concurrent ballots, 3 nodes"}, "No failures, 2 concurrent ballots, 3 nodes"},
# {&PaxosTest.run_simple_2/3, TestUtil.get_local_config(3), 10, {&PaxosTest.run_simple_2/3, TestUtil.get_local_config(3), 10,
# "No failures, 2 concurrent ballots, 3 local procs"}, "No failures, 2 concurrent ballots, 3 local procs"},
# {&PaxosTest.run_simple_3/3, TestUtil.get_local_config(3), 10, {&PaxosTest.run_simple_3/3, TestUtil.get_local_config(3), 10,
# "No failures, 2 concurrent instances, 3 local procs"}, "No failures, 2 concurrent instances, 3 local procs"},
# {&PaxosTest.run_simple_many_1/3, TestUtil.get_dist_config(host, 5), 10, {&PaxosTest.run_simple_many_1/3, TestUtil.get_dist_config(host, 5), 10,
# "No failures, many concurrent ballots 1, 5 nodes"}, "No failures, many concurrent ballots 1, 5 nodes"},
# {&PaxosTest.run_simple_many_1/3, TestUtil.get_local_config(5), 10, {&PaxosTest.run_simple_many_1/3, TestUtil.get_local_config(5), 10,
# "No failures, many concurrent ballots 1, 5 local procs"}, "No failures, many concurrent ballots 1, 5 local procs"},
# {&PaxosTest.run_simple_many_2/3, TestUtil.get_dist_config(host, 5), 10, {&PaxosTest.run_simple_many_2/3, TestUtil.get_dist_config(host, 5), 10,
# "No failures, many concurrent ballots 2, 5 nodes"}, "No failures, many concurrent ballots 2, 5 nodes"},
# {&PaxosTest.run_simple_many_2/3, TestUtil.get_local_config(5), 10, {&PaxosTest.run_simple_many_2/3, TestUtil.get_local_config(5), 10,
# "No failures, many concurrent ballots 2, 5 local procs"}, "No failures, many concurrent ballots 2, 5 local procs"},
# {&PaxosTest.run_non_leader_crash/3, TestUtil.get_dist_config(host, 3), 10, {&PaxosTest.run_non_leader_crash/3, TestUtil.get_dist_config(host, 3), 10,
# "One non-leader crashes, no concurrent ballots, 3 nodes"}, "One non-leader crashes, no concurrent ballots, 3 nodes"},
# {&PaxosTest.run_non_leader_crash/3, TestUtil.get_local_config(3), 10, {&PaxosTest.run_non_leader_crash/3, TestUtil.get_local_config(3), 10,
# "One non-leader crashes, no concurrent ballots, 3 local procs"}, "One non-leader crashes, no concurrent ballots, 3 local procs"},
# {&PaxosTest.run_minority_non_leader_crash/3, TestUtil.get_dist_config(host, 5), 10, {&PaxosTest.run_minority_non_leader_crash/3, TestUtil.get_dist_config(host, 5), 10,
# "Minority non-leader crashes, no concurrent ballots"}, "Minority non-leader crashes, no concurrent ballots"},
# {&PaxosTest.run_minority_non_leader_crash/3, TestUtil.get_local_config(5), 10, {&PaxosTest.run_minority_non_leader_crash/3, TestUtil.get_local_config(5), 10,
# "Minority non-leader crashes, no concurrent ballots"}, "Minority non-leader crashes, no concurrent ballots"},
# {&PaxosTest.run_leader_crash_simple/3, TestUtil.get_dist_config(host, 5), 10, {&PaxosTest.run_leader_crash_simple/3, TestUtil.get_dist_config(host, 5), 10,
# "Leader crashes, no concurrent ballots, 5 nodes"}, "Leader crashes, no concurrent ballots, 5 nodes"},
# {&PaxosTest.run_leader_crash_simple/3, TestUtil.get_local_config(5), 10, {&PaxosTest.run_leader_crash_simple/3, TestUtil.get_local_config(5), 10,
# "Leader crashes, no concurrent ballots, 5 local procs"}, "Leader crashes, no concurrent ballots, 5 local procs"},
# {&PaxosTest.run_leader_crash_simple_2/3, TestUtil.get_dist_config(host, 7), 10, {&PaxosTest.run_leader_crash_simple_2/3, TestUtil.get_dist_config(host, 7), 10,
# "Leader and some non-leaders crash, no concurrent ballots, 7 nodes"}, "Leader and some non-leaders crash, no concurrent ballots, 7 nodes"},
# {&PaxosTest.run_leader_crash_simple_2/3, TestUtil.get_local_config(7), 10, {&PaxosTest.run_leader_crash_simple_2/3, TestUtil.get_local_config(7), 10,
# "Leader and some non-leaders crash, no concurrent ballots, 7 local procs"}, "Leader and some non-leaders crash, no concurrent ballots, 7 local procs"},
{&PaxosTest.run_leader_crash_complex/3, TestUtil.get_dist_config(host, 11), 10, {&PaxosTest.run_leader_crash_complex/3, TestUtil.get_dist_config(host, 11), 10,
"Cascading failures of leaders and non-leaders, 11 nodes"}, "Cascading failures of leaders and non-leaders, 11 nodes"},
{&PaxosTest.run_leader_crash_complex/3, TestUtil.get_local_config(11), 10, {&PaxosTest.run_leader_crash_complex/3, TestUtil.get_local_config(11), 10,
@ -69,10 +69,10 @@ test_suite = [
# Aditional Test functions # Aditional Test functions
# {&PaxosTestAditional.run_leader_crash_simple_before_decision/3, TestUtil.get_dist_config(host, 5), 10, {&PaxosTestAditional.run_leader_crash_simple_before_decision/3, TestUtil.get_dist_config(host, 5), 10,
# "Leader crashes right before decision, no concurrent ballots, 5 nodes"}, "Leader crashes right before decision, no concurrent ballots, 5 nodes"},
# {&PaxosTestAditional.run_leader_crash_simple_before_decision/3, TestUtil.get_local_config(5), 10, {&PaxosTestAditional.run_leader_crash_simple_before_decision/3, TestUtil.get_local_config(5), 10,
# "Leader crashes right before decision, no concurrent ballots, 5 local procs"}, "Leader crashes right before decision, no concurrent ballots, 5 local procs"},
] ]
Node.stop() Node.stop()