fixed compiler errors and updated read me
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
98
lib/paxos.ex
98
lib/paxos.ex
@@ -21,10 +21,8 @@ defmodule Utils do
|
||||
"""
|
||||
@min_print_level 3
|
||||
|
||||
@doc """
|
||||
This function works similiary with unicast but it allows both for a pid or an atom
|
||||
to be given as the first parameter
|
||||
"""
|
||||
# This function works similiary with unicast but it allows both for a pid or an atom
|
||||
# to be given as the first parameter
|
||||
def safecast(p, m) when p == nil, do: IO.puts('Trying to safecast #{m} with p as nil')
|
||||
def safecast(p, m) when is_pid(p), do: send(p, m)
|
||||
def safecast(p, m) do
|
||||
@@ -132,9 +130,7 @@ defmodule Paxos do
|
||||
|
||||
create_log 0
|
||||
|
||||
@doc """
|
||||
This macro allows the state.instmap to be updated very easily
|
||||
"""
|
||||
# This macro allows the state.instmap to be updated very easily
|
||||
defmacrop set_instmap(do: expr) do
|
||||
quote do
|
||||
var!(map) = var!(state).instmap[var!(inst)]
|
||||
@@ -171,9 +167,7 @@ defmodule Paxos do
|
||||
run(state)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Guarantees that a specific state exists for a specific instance
|
||||
"""
|
||||
# Guarantees that a specific state exists for a specific instance
|
||||
defp has_or_create(state, inst, value \\ nil, pid_to_inform \\ nil, action \\ nil) do
|
||||
or_state state.instmap[inst] == nil do
|
||||
instmap =
|
||||
@@ -197,11 +191,9 @@ defmodule Paxos do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Checks if an instance has finished or if it was aborted.
|
||||
If the optional parameter ignore_aborted was set to true makes this function only check
|
||||
if the the instance has finished
|
||||
"""
|
||||
# Checks if an instance has finished or if it was aborted.
|
||||
# If the optional parameter ignore_aborted was set to true makes this function only check
|
||||
# if the the instance has finished
|
||||
defp has_finished(state, inst, ignore_aborted \\ false) do
|
||||
cond do
|
||||
Map.has_key?(state.decided, inst) -> true
|
||||
@@ -211,21 +203,19 @@ defmodule Paxos do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
This is the run/recieve function
|
||||
All the messages that are handled by this function are:
|
||||
{:ele_trust, proc} ->
|
||||
{:propose, inst, value, pid_to_inform, action} ->
|
||||
{:rb_deliver, proc, {:other_propose, inst, value}} ->
|
||||
{:rb_deliver, proc, {:prepare, proc, inst, ballot}} ->
|
||||
{:nack, inst, ballot} ->
|
||||
{:rb_deliver, _proc, {:abort, inst, ballot}} ->
|
||||
{:prepared, inst, ballot, accepted_ballot, accepted_value} ->
|
||||
{:rb_deliver, proc, {:accept, inst, ballot, value}} ->
|
||||
{:accepted, inst, ballot} ->
|
||||
{:get_value, inst, pid_to_inform} ->
|
||||
{:rb_deliver, _, {:decide, inst, value}} ->
|
||||
"""
|
||||
# This is the run/recieve function
|
||||
# All the messages that are handled by this function are:
|
||||
# {:ele_trust, proc} ->
|
||||
# {:propose, inst, value, pid_to_inform, action} ->
|
||||
# {:rb_deliver, proc, {:other_propose, inst, value}} ->
|
||||
# {:rb_deliver, proc, {:prepare, proc, inst, ballot}} ->
|
||||
# {:nack, inst, ballot} ->
|
||||
# {:rb_deliver, _proc, {:abort, inst, ballot}} ->
|
||||
# {:prepared, inst, ballot, accepted_ballot, accepted_value} ->
|
||||
# {:rb_deliver, proc, {:accept, inst, ballot, value}} ->
|
||||
# {:accepted, inst, ballot} ->
|
||||
# {:get_value, inst, pid_to_inform} ->
|
||||
# {:rb_deliver, _, {:decide, inst, value}} ->
|
||||
runfn do
|
||||
# Handles leader elector
|
||||
{:ele_trust, proc} ->
|
||||
@@ -253,6 +243,8 @@ defmodule Paxos do
|
||||
%{map| ballot: Ballot.inc(map.ballot)}
|
||||
end
|
||||
|
||||
state
|
||||
|
||||
not Map.has_key?(state.instmap, inst) ->
|
||||
EagerReliableBroadcast.broadcast(state.name, {:other_propose, inst, value})
|
||||
state = has_or_create(state, inst, value, pid_to_inform, action)
|
||||
@@ -277,7 +269,7 @@ defmodule Paxos do
|
||||
end
|
||||
|
||||
# Handles the sharing of a proposal value to other processes
|
||||
{:rb_deliver, proc, {:other_propose, inst, value}} ->
|
||||
{:rb_deliver, _, {:other_propose, inst, value}} ->
|
||||
cond do
|
||||
has_finished(state, inst, true) ->
|
||||
EagerReliableBroadcast.broadcast(
|
||||
@@ -310,6 +302,7 @@ defmodule Paxos do
|
||||
set_instmap do
|
||||
%{ map | ballot: ballot }
|
||||
end
|
||||
state
|
||||
|
||||
Ballot.compare(ballot, &>/2, state.instmap[inst].ballot) ->
|
||||
safecast(proc,
|
||||
@@ -320,6 +313,7 @@ defmodule Paxos do
|
||||
set_instmap do
|
||||
%{ map | ballot: ballot }
|
||||
end
|
||||
state
|
||||
|
||||
true ->
|
||||
safecast(proc, {:nack, inst, ballot})
|
||||
@@ -349,12 +343,13 @@ defmodule Paxos do
|
||||
}
|
||||
end
|
||||
|
||||
state
|
||||
true ->
|
||||
state
|
||||
end
|
||||
|
||||
# Handles an abort
|
||||
{:rb_deliver, _proc, {:abort, inst, ballot}} ->
|
||||
{:rb_deliver, _proc, {:abort, inst, _}} ->
|
||||
cond do
|
||||
has_finished(state, inst) ->
|
||||
state
|
||||
@@ -418,6 +413,7 @@ defmodule Paxos do
|
||||
accepted_ballot: ballot
|
||||
}
|
||||
end
|
||||
state
|
||||
else
|
||||
log("#{state.name} -> #{proc} nack")
|
||||
safecast(proc, {:nack, inst, ballot})
|
||||
@@ -471,10 +467,8 @@ defmodule Paxos do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Does the logic to decide when to send the prepare messages
|
||||
Also sets the state nessesary to run the proposal
|
||||
"""
|
||||
# Does the logic to decide when to send the prepare messages
|
||||
# Also sets the state nessesary to run the proposal
|
||||
defp prepare(state, _) when state.leader != state.name, do: state
|
||||
defp prepare(state, inst) do
|
||||
cond do
|
||||
@@ -505,15 +499,14 @@ defmodule Paxos do
|
||||
has_sent_accept: false
|
||||
}
|
||||
end
|
||||
state
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Processes the prepared messages and when a quorum is met the accept messages are send
|
||||
"""
|
||||
# Processes the prepared messages and when a quorum is met the accept messages are send
|
||||
defp prepared(state, _) when state.leader != state.name, do: state
|
||||
defp prepared(state, inst) do
|
||||
if length(state.instmap[inst].prepared_values) >= floor(length(state.processes) / 2) + 1 and
|
||||
or_state length(state.instmap[inst].prepared_values) >= floor(length(state.processes) / 2) + 1 and
|
||||
not state.instmap[inst].has_sent_accept do
|
||||
{_, a_val} =
|
||||
Enum.reduce(state.instmap[inst].prepared_values, {Ballot.init(state.name, 0), nil}, fn {bal, val},
|
||||
@@ -550,14 +543,11 @@ defmodule Paxos do
|
||||
has_sent_accept: true
|
||||
}
|
||||
end
|
||||
else
|
||||
state
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Processes the accepted messages and when a qurum is met decide on the value
|
||||
"""
|
||||
# Processes the accepted messages and when a qurum is met decide on the value
|
||||
defp accepted(state, _) when state.leader != state.name, do: state
|
||||
defp accepted(state, inst) do
|
||||
or_state state.instmap[inst].accepted >= floor(length(state.processes) / 2) + 1 do
|
||||
@@ -598,9 +588,7 @@ defmodule Paxos do
|
||||
propose_loop(inst, t)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Waits the right message from the paxos replica
|
||||
"""
|
||||
# Waits the right message from the paxos replica
|
||||
defp propose_loop(inst, t) do
|
||||
receive do
|
||||
{:timeout, ^inst} -> {:timeout}
|
||||
@@ -622,9 +610,7 @@ defmodule Paxos do
|
||||
get_decision_loop(inst, t)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Sends waits for the right message from the paxos replica
|
||||
"""
|
||||
# Sends waits for the right message from the paxos replica
|
||||
defp get_decision_loop(inst, t) do
|
||||
receive do
|
||||
{:get_value_res, ^inst, v} ->
|
||||
@@ -661,9 +647,7 @@ defmodule Ballot do
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Compare the name of 2 processes and select the lowest one
|
||||
"""
|
||||
# Compare the name of 2 processes and select the lowest one
|
||||
defp lexicographical_compare(a, b) do
|
||||
cond do
|
||||
a == b -> 0
|
||||
@@ -672,9 +656,7 @@ defmodule Ballot do
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Callculate the difference between w ballots
|
||||
"""
|
||||
# Callculate the difference between w ballots
|
||||
defp diff({name1, number1}, {name2, number2}) do
|
||||
diff = number1 - number2
|
||||
if diff == 0 do
|
||||
@@ -701,9 +683,7 @@ defmodule EagerReliableBroadcast do
|
||||
require Utils
|
||||
import Utils
|
||||
|
||||
@doc """
|
||||
Removes _br from the name of a process
|
||||
"""
|
||||
# Removes _br from the name of a process
|
||||
defp get_non_rb_name(name) do
|
||||
String.to_atom(String.replace(Atom.to_string(name), "_rb", ""))
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user