Skip to content

Commit ad2eba1

Browse files
committed
enforce max_counter violations on send and recv
1 parent d031518 commit ad2eba1

3 files changed

Lines changed: 48 additions & 18 deletions

File tree

lib/hlclock/server.ex

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ defmodule HLClock.Server do
3434
end
3535

3636
def handle_call(:send_timestamp, _from, data) do
37-
{:ok, timestamp} = Timestamp.send(data.timestamp, physical_time())
38-
{:reply, {:ok, timestamp}, %{data | timestamp: timestamp}}
37+
case Timestamp.send(data.timestamp, physical_time()) do
38+
{:ok, timestamp} ->
39+
{:reply, {:ok, timestamp}, %{data | timestamp: timestamp}}
40+
41+
{:error, error} ->
42+
{:reply, {:error, error}, data}
43+
end
3944
end
4045

4146
def handle_call(
@@ -55,8 +60,13 @@ defmodule HLClock.Server do
5560
def handle_info(:periodic_send, data) do
5661
Process.send_after(self(), :periodic_send, interval(data))
5762

58-
{:ok, ts} = Timestamp.send(data.timestamp, physical_time(), data.max_drift)
59-
{:noreply, %{data | timestamp: ts}}
63+
case Timestamp.send(data.timestamp, physical_time()) do
64+
{:ok, ts} ->
65+
{:noreply, %{data | timestamp: ts}}
66+
67+
{:error, _} ->
68+
{:noreply, data}
69+
end
6070
end
6171

6272
defp physical_time, do: System.os_time(:millisecond)

lib/hlclock/timestamp.ex

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ defmodule HLClock.Timestamp do
4646
def send(%{time: old_time, counter: counter, node_id: node_id}, pt) do
4747
new_time = max(old_time, pt)
4848
new_counter = advance_counter(old_time, counter, new_time)
49-
{:ok, new(new_time, new_counter, node_id)}
49+
50+
case handle_counter(new_counter) do
51+
:ok -> {:ok, new(new_time, new_counter, node_id)}
52+
err -> err
53+
end
5054
end
5155

5256
# Compatibility for older users of Timestamp that may be providing the max_drift.
@@ -67,15 +71,9 @@ defmodule HLClock.Timestamp do
6771
new_time = Enum.max([physical_time, local.time, remote.time])
6872

6973
with {:ok, node_id} <- compare_node_ids(local.node_id, remote.node_id),
70-
:ok <-
71-
handle_drift(
72-
remote.time,
73-
physical_time,
74-
max_drift,
75-
:remote_drift_violation
76-
),
77-
:ok <- handle_drift(new_time, physical_time, max_drift),
78-
new_counter <- merge_logical(new_time, local, remote) do
74+
:ok <- handle_drift(remote.time, physical_time, max_drift),
75+
new_counter <- merge_logical(new_time, local, remote),
76+
:ok <- handle_counter(new_counter) do
7977
{:ok, new(new_time, new_counter, node_id)}
8078
end
8179
end
@@ -183,10 +181,10 @@ defmodule HLClock.Timestamp do
183181
end
184182
end
185183

186-
defp handle_drift(l, pt, max_drift, err \\ :clock_drift_violation) do
184+
defp handle_drift(l, pt, max_drift) do
187185
cond do
188186
drift?(l, pt, max_drift) ->
189-
{:error, err}
187+
{:error, :remote_drift_violation}
190188

191189
true ->
192190
:ok
@@ -207,6 +205,14 @@ defmodule HLClock.Timestamp do
207205
end
208206
end
209207

208+
defp handle_counter(counter) do
209+
if counter > 0xFFFF do
210+
{:error, :max_counter_violation}
211+
else
212+
:ok
213+
end
214+
end
215+
210216
defimpl String.Chars do
211217
def to_string(ts) do
212218
logical_time =

test/hlclock/timestamp_test.exs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ defmodule HLClock.TimestampTest do
9191
property "for a fixed physical time, logical counter incremented" do
9292
check all(time <- ntp_millis()) do
9393
t0 = Timestamp.new(time, 0)
94-
{:ok, t1} = Timestamp.send(t0, 0, @max_drift)
94+
{:ok, t1} = Timestamp.send(t0, 0)
9595
assert t0.counter == 0
9696
assert t1.counter == 1
9797
refute Timestamp.before?(t1, t0)
@@ -100,10 +100,15 @@ defmodule HLClock.TimestampTest do
100100

101101
test "physical time can move backwards" do
102102
t0 = Timestamp.new(10, 0, 0)
103-
{:ok, t1} = Timestamp.send(t0, 9, @max_drift)
103+
{:ok, t1} = Timestamp.send(t0, 9)
104104
assert t0.time == t1.time
105105
assert t1.counter == 1
106106
end
107+
108+
test "max counter exception" do
109+
t0 = Timestamp.new(10, 0xFFFF, 0)
110+
assert {:error, :max_counter_violation} == Timestamp.send(t0, 9)
111+
end
107112
end
108113

109114
describe "recv_timestamp/2" do
@@ -116,6 +121,15 @@ defmodule HLClock.TimestampTest do
116121
assert t2.node_id == 0
117122
end
118123

124+
test "max counter exception" do
125+
t0 = Timestamp.new(10, 0xFFFF, 0)
126+
remote = Timestamp.new(9, 0xFFFF, 1)
127+
pt = 9
128+
129+
assert {:error, :max_counter_violation} ==
130+
Timestamp.recv(t0, remote, pt, @max_drift)
131+
end
132+
119133
test "events test" do
120134
events = [
121135
# valid steps

0 commit comments

Comments
 (0)