pessimistic init

Signed-off-by: Yilin Chen <sticnarf@gmail.com>
This commit is contained in:
Yilin Chen 2019-10-21 16:36:56 +08:00
parent e3714440db
commit 33e2a83627
No known key found for this signature in database
GPG Key ID: 353E7ED34BF326E0
2 changed files with 183 additions and 0 deletions

View File

@ -0,0 +1,153 @@
----------------------- MODULE PessimisticTransaction -----------------------
EXTENDS Integers
\* The set of transaction keys.
CONSTANTS KEY
ASSUME KEY # {} \* Keys cannot be empty.
\* The set of clients to execute a transaction.
CONSTANTS CLIENT
\* next_ts is the timestamp for transaction. It is increased monotonically,
\* so every transaction must have a unique start and commit ts.
VARIABLES next_ts
\* client_state[c] is the state of client.
VARIABLES client_state
\* client_ts[c] is a record of [start_ts, for_update_ts, commit_ts].
VARIABLES client_ts
\* client_key[c] is a record of [primary: key, secondary: {key},
\* pessimistic: {key}, pending: {key}]. Hereby, "pessimistic" denotes
\* the keys whose pessimistic locks haven't been acquired, "pending"
\* denotes the keys that are pending for prewrite.
VARIABLES client_key
\* key_data[k] is the set of multi-version data of the key.
\* Since we don't care about the concrete value of data, a record of
\* [ts: start_ts] is sufficient to represent one data version.
VARIABLES key_data
\* key_lock[k] is the set of lock. A lock is of a record of [ts: start_ts,
\* for_update_ts, primary: key]. If primary equals to k, it is a primary
\* lock, otherwise secondary lock. If for_update_ts > 0, it belongs to a
\* pessimistic transaction.
VARIABLES key_lock
\* key_write[k] is a sequence of committed version of the key.
\* A committed version of the key is a record of [ts, type, start_ts].
\* type can be "write" or "rollback" depending on record type. start_ts
\* field only exists if type is "write". For "write" record, ts denotes
\* commit_ts; for "rollback" record, $ts$ denotes start_ts.
VARIABLES key_write
\* key_last_read_ts is for verifying snapshot isolation invariant. It should
\* not appear in a real-world implementation.
\*
\* key_last_read_ts[k] denotes the last read timestamp for key k, this
\* should be monotonic.
VARIABLES key_last_read_ts
\* The set of all messages sent by clients. To simulate message resending,
\* client messages are inserted to the set and never deleted. The server can
\* pick any message in the set to execute.
VARIABLES msg
client_vars == <<client_state, client_ts, client_key>>
key_vars == <<key_data, key_lock, key_write, key_last_read_ts>>
vars == <<next_ts, client_vars, key_vars, msg>>
-----------------------------------------------------------------------------
Pos == {x \in Nat : x > 0}
-----------------------------------------------------------------------------
Init ==
/\ next_ts = 1
/\ client_state = [c \in CLIENT |-> "init"]
/\ client_ts = [c \in CLIENT |-> [start_ts |-> 0,
for_update_ts |-> 0,
commit_ts |-> 0]
]
/\ client_key = [c \in CLIENT |-> {}]
/\ key_lock = [k \in KEY |-> {}]
/\ key_data = [k \in KEY |-> {}]
/\ key_write = [k \in KEY |-> {}]
/\ key_last_read_ts = [k \in KEY |-> 0]
/\ msg = {}
Next ==
UNCHANGED <<client_vars, key_vars, vars>>
-----------------------------------------------------------------------------
NextTsTypeInv == next_ts \in Pos
ClientStateTypeInv ==
client_state \in [
CLIENT -> {"init", "working", "prewriting",
"committing", "committed", "aborted"}
]
ClientTsTypeInv ==
client_ts \in
[CLIENT -> [start_ts : Nat, for_update_ts: Nat, commit_ts : Nat]]
ClientKeyTypeInv ==
client_key \in [
CLIENT -> {{}} \union [
primary: KEY,
secondary: SUBSET KEY,
pessimistic: SUBSET KEY,
pending : SUBSET KEY
]
]
KeyDataTypeInv ==
key_data \in [KEY -> SUBSET [ts: Pos]]
KeyLockTypeInv ==
key_lock \in [KEY -> SUBSET [ts: Pos, for_update_ts: Nat, primary: KEY]]
KeyWriteTypeInv ==
key_write \in [KEY ->
SUBSET [ts: Pos, type: {"write", "rollback"}, start_ts: Pos]
]
KeyWriteStartTsInv ==
\A k \in DOMAIN key_write:
LET
rec == key_write[k]
IN
\/ rec = {}
\/ IF rec.type = "write"
THEN rec.ts > rec.start_ts
ELSE rec.type = "rollback" /\ rec.ts = rec.start_ts
KeyLastReadTsTypeInv ==
key_last_read_ts \in [KEY -> Nat]
MsgTypeInv ==
msg \subseteq (
[c: CLIENT, type: {"lock", "prewrite"}, key: KEY,
start_ts: Pos, for_update_ts: Pos] \union
[c: CLIENT, type: {"commit"}, key: KEY, commit_ts: Pos] \union
[c: CLIENT, type: {"rollback"}, key: KEY]
)
TypeInvariant ==
/\ NextTsTypeInv
/\ ClientStateTypeInv
/\ ClientTsTypeInv
/\ ClientKeyTypeInv
/\ KeyDataTypeInv
/\ KeyLockTypeInv
/\ KeyWriteTypeInv
/\ KeyWriteStartTsInv
/\ KeyLastReadTsTypeInv
/\ MsgTypeInv
=============================================================================

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.lamport.tla.toolbox.tool.tlc.modelCheck">
<stringAttribute key="configurationName" value="Test1"/>
<intAttribute key="distributedFPSetCount" value="0"/>
<stringAttribute key="distributedNetworkInterface" value="192.168.220.40"/>
<intAttribute key="distributedNodesCount" value="1"/>
<stringAttribute key="distributedTLC" value="off"/>
<intAttribute key="fpIndex" value="80"/>
<intAttribute key="maxHeapSize" value="25"/>
<stringAttribute key="modelBehaviorInit" value="Init"/>
<stringAttribute key="modelBehaviorNext" value="Next"/>
<stringAttribute key="modelBehaviorSpec" value=""/>
<intAttribute key="modelBehaviorSpecType" value="2"/>
<stringAttribute key="modelBehaviorVars" value="key_last_read_ts, client_ts, client_state, key_lock, key_write, msg, client_key, next_ts, key_data"/>
<stringAttribute key="modelComments" value=""/>
<booleanAttribute key="modelCorrectnessCheckDeadlock" value="false"/>
<listAttribute key="modelCorrectnessInvariants">
<listEntry value="1TypeInvariant"/>
</listAttribute>
<listAttribute key="modelCorrectnessProperties"/>
<stringAttribute key="modelExpressionEval" value=""/>
<listAttribute key="modelParameterConstants">
<listEntry value="KEY;;{1, 2};0;0"/>
<listEntry value="CLIENT;;{c1, c2};1;0"/>
</listAttribute>
<intAttribute key="numberOfWorkers" value="6"/>
<stringAttribute key="result.mail.address" value=""/>
<stringAttribute key="specName" value="PessimisticTransaction"/>
<stringAttribute key="tlcResourcesProfile" value="local custom"/>
</launchConfiguration>