Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added WriteAndVerify committing #44

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions PutAndVerify/MC.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
\* MV CONSTANT declarations
CONSTANTS
Alice = Alice
Bob = Bob
\* MV CONSTANT definitions
CONSTANT
CLIENTS <- const_172889209848054000
\* SYMMETRY definition
SYMMETRY symm_172889209848055000
\* CONSTANT definitions
CONSTANT
WITH_CRASHING <- const_172889209848056000
\* CONSTANT definitions
CONSTANT
WITH_RO <- const_172889209848057000
\* SPECIFICATION definition
SPECIFICATION
WVSpec
\* INVARIANT definition
INVARIANT
WVConsistency
WVTypeOk
\* Generated on Mon Oct 14 15:48:18 CST 2024
31 changes: 31 additions & 0 deletions PutAndVerify/MC.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---- MODULE MC ----
EXTENDS WriteAndVerify, TLC

\* MV CONSTANT declarations@modelParameterConstants
CONSTANTS
Alice, Bob
----

\* MV CONSTANT definitions CLIENTS
const_172889209848054000 ==
{Alice, Bob}
----

\* SYMMETRY definition
symm_172889209848055000 ==
Permutations(const_172889209848054000)
----

\* CONSTANT definitions @modelParameterConstants:1WITH_CRASHING
const_172889209848056000 ==
FALSE
----

\* CONSTANT definitions @modelParameterConstants:2WITH_RO
const_172889209848057000 ==
FALSE
----

=============================================================================
\* Modification History
\* Created Mon Oct 14 15:48:18 CST 2024 by Hillium
10 changes: 10 additions & 0 deletions PutAndVerify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Put and Verify Committing

This algorithm allows you write to a file exactly-once in a object storage
supports `PUT` and `LIST` and the two operations have strong consistency.

The model constants:

- `CLIENTS`: The participants of the algorithm.
- `WITH_CRASHING`: Allow any of participants crash after sending a write message before receiving a response.
- `WITH_RO`: Allow "read-only" clients to participate. The algorithm then becomes a `RWLock` implementation: *many of "read-only" clients commit* or *exactly one of "read-write" client commits*.
93 changes: 93 additions & 0 deletions PutAndVerify/WriteAndVerify.tla
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
--------------------------- MODULE WriteAndVerify ---------------------------

CONSTANT CLIENTS, WITH_RO, WITH_CRASHING

VARIABLE storage, clState, clFavor

Vars == << storage, clState, clFavor >>

WVTypeOk == /\ storage \in [ CLIENTS -> { "none", "empty", "written", "written-ro", "empty-ro" } ]
/\ clState \in [ CLIENTS -> { "begin", "precheck-done", "blank-written",
"write-check-done", "committed", "aborted", "crashed" } ]
/\ clFavor \in [ CLIENTS -> { "read-write", "read-only" } ]

WVInit == /\ storage = [ cli \in CLIENTS |-> "none" ]
/\ clState = [ cli \in CLIENTS |-> "begin" ]
/\ clFavor = [ cli \in CLIENTS |-> "read-write" ]

(* Only one execution can be committed. *)
(* Once committed, the file has been written. *)
WVConsistency == /\ \A i, j \in CLIENTS :
i /= j /\ storage[i] = "written" => ~storage[j] \in { "written", "written-ro" }

(* "Verify" condition: storage only contains our file or nothing. *)
Check(c) == /\ clFavor[c] = "read-write" =>
\A f \in CLIENTS : f /= c => storage[f] = "none"
/\ clFavor[c] = "read-only" =>
(* No conflicting write. *)
\A f \in CLIENTS : f /= c => ~storage[f] \in { "empty", "written" }

Precheck(c) == /\ clState[c] = "begin"
/\ IF Check(c)
THEN clState' = [ clState EXCEPT ![c] = "precheck-done" ]
ELSE clState' = [ clState EXCEPT ![c] = "aborted" ]
/\ UNCHANGED << storage, clFavor >>

IsRO(c) == clFavor[c] = "read-only"

DoWriteBlank(c) == /\ clState[c] = "precheck-done"
/\ storage' = [ storage EXCEPT ![c] = IF IsRO(c) THEN "empty-ro" ELSE "empty" ]

WriteBlank(c) == /\ DoWriteBlank(c)
/\ clState' = [ clState EXCEPT ![c] = "blank-written" ]
/\ UNCHANGED << clFavor >>


ConflictCheck(c) == /\ clState[c] = "blank-written"
/\ IF Check(c)
THEN clState' = [ clState EXCEPT ![c] = "write-check-done" ]
ELSE clState' = [ clState EXCEPT ![c] = "aborted" ]
/\ UNCHANGED << storage, clFavor >>

(* Delete the file when aborted. *)
RollBack(c) == /\ clState[c] = "aborted"
/\ storage[c] /= "none"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary?

Copy link
Author

@YuJuncen YuJuncen Oct 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact not. This won't create new states but just adding arrows between states.

However our implmentation includes this, so I left it here.

/\ storage' = [ storage EXCEPT ![c] = "none" ]
/\ clState' = [ clState EXCEPT ![c] = "begin" ]
/\ UNCHANGED << clFavor >>

DoCommit(c) == /\ clState[c] = "write-check-done"
/\ storage' = [ storage EXCEPT ![c] = IF IsRO(c) THEN "written-ro" ELSE "written" ]

Commit(c) == /\ DoCommit(c)
/\ clState' = [ clState EXCEPT ![c] = "committed" ]
/\ UNCHANGED << clFavor >>

BeRO(c) == /\ clState[c] = "begin"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the actual meaning of BeRO? client can generate "empty-ro" in storage but I don't know why it should exist

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BeRO means become a "read-only" node. Then the algorithm become a implementation of RWLock instead of Mutex.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, there can be many storage slots contains "written-ro" or exactly one storage slot contains "written". (RWLock)

/\ clFavor[c] = "read-write"
/\ clFavor' = [ clFavor EXCEPT ![c] = "read-only" ]
/\ UNCHANGED << clState, storage >>

WrittenAndCrash(c) == /\ clState[c] = "precheck-done" \/ clState[c] = "write-check-done"
lance6716 marked this conversation as resolved.
Show resolved Hide resolved
/\ clState' = [ clState EXCEPT ![c] = "crashed" ]
/\ DoWriteBlank(c) \/ DoCommit(c)
/\ UNCHANGED << clFavor >>


WVNext == \E c \in CLIENTS: \/ Precheck(c)
\/ WriteBlank(c)
\/ ConflictCheck(c)
\/ RollBack(c)
\/ Commit(c)
\/ WITH_CRASHING /\ WrittenAndCrash(c)
\/ WITH_RO /\ BeRO(c)


WVSpec == WVInit /\ [][WVNext]_Vars

THEOREM WVSpec => [](WVConsistency /\ WVTypeOk)

=============================================================================
\* Modification History
\* Last modified Mon Oct 14 15:38:01 CST 2024 by Hillium
\* Created Sat Jun 29 10:41:34 CST 2024 by Hillium