Model prepared artifact selection before lease acquisition

This commit is contained in:
ms2k 2026-07-22 00:58:23 +09:00
commit d799cf4837
2 changed files with 112 additions and 38 deletions

View file

@ -3,11 +3,12 @@ CONSTANTS
G2 = g2 G2 = g2
P1 = p1 P1 = p1
P2 = p2 P2 = p2
A1 = a1 A1 = incarnation1
A2 = incarnation2
NoArtifact = noArtifact NoArtifact = noArtifact
Generations <- GenerationsFixture Generations <- GenerationsFixture
Preparations <- PreparationsFixture Preparations <- PreparationsFixture
Artifact = a1 Artifact = artifact
SPECIFICATION Spec SPECIFICATION Spec
CHECK_DEADLOCK FALSE CHECK_DEADLOCK FALSE
@ -15,6 +16,8 @@ CHECK_DEADLOCK FALSE
INVARIANTS INVARIANTS
TypeOK TypeOK
PrepareOwnershipConsistent PrepareOwnershipConsistent
ArtifactIncarnationConsistent
SelectionBindingConsistent
LiveOwnedStageNotRecoverable LiveOwnedStageNotRecoverable
LostOwnedStageRecoverable LostOwnedStageRecoverable
LostIntentRecoverable LostIntentRecoverable
@ -23,5 +26,7 @@ INVARIANTS
MountedGenerationLeased MountedGenerationLeased
LeasedArtifactPublished LeasedArtifactPublished
GCExcludesLeases GCExcludesLeases
GCExcludesSelections
SelectedArtifactStable
ReplacementOnlyDuringGC ReplacementOnlyDuringGC
ForeignStagePreserved ForeignStagePreserved

View file

@ -15,17 +15,21 @@ CONSTANTS
G2, G2,
P1, P1,
P2, P2,
A1 A1,
A2
ASSUME ASSUME
/\ Generations = {G1, G2} /\ Generations = {G1, G2}
/\ G1 # G2 /\ G1 # G2
/\ Preparations = {P1, P2} /\ Preparations = {P1, P2}
/\ P1 # P2 /\ P1 # P2
/\ Artifact = A1
/\ NoArtifact # Artifact /\ NoArtifact # Artifact
/\ A1 # A2
/\ NoArtifact \notin {A1, A2}
/\ Artifact \notin {A1, A2}
ArtifactStates == {"Absent", "Published"} ArtifactStates == {"Absent", "Published"}
ArtifactIncarnations == {A1, A2}
StageStates == {"Absent", "Owned", "Foreign"} StageStates == {"Absent", "Owned", "Foreign"}
MaterializerStates == {"Absent", "Live", "Lost"} MaterializerStates == {"Absent", "Live", "Lost"}
GenerationsFixture == {G1, G2} GenerationsFixture == {G1, G2}
@ -33,10 +37,12 @@ PreparationsFixture == {P1, P2}
VARIABLES VARIABLES
artifactState, artifactState,
artifactIncarnation,
stageState, stageState,
prepareIntent, prepareIntent,
materializerState, materializerState,
leases, leases,
selectionBinding,
mounts, mounts,
artifactBinding, artifactBinding,
gcRequested, gcRequested,
@ -45,10 +51,12 @@ VARIABLES
vars == << vars == <<
artifactState, artifactState,
artifactIncarnation,
stageState, stageState,
prepareIntent, prepareIntent,
materializerState, materializerState,
leases, leases,
selectionBinding,
mounts, mounts,
artifactBinding, artifactBinding,
gcRequested, gcRequested,
@ -58,10 +66,12 @@ vars == <<
Init == Init ==
/\ artifactState = "Absent" /\ artifactState = "Absent"
/\ artifactIncarnation = NoArtifact
/\ stageState = [p \in Preparations |-> "Absent"] /\ stageState = [p \in Preparations |-> "Absent"]
/\ prepareIntent = [p \in Preparations |-> FALSE] /\ prepareIntent = [p \in Preparations |-> FALSE]
/\ materializerState = [p \in Preparations |-> "Absent"] /\ materializerState = [p \in Preparations |-> "Absent"]
/\ leases = {} /\ leases = {}
/\ selectionBinding = [g \in Generations |-> NoArtifact]
/\ mounts = {} /\ mounts = {}
/\ artifactBinding = [g \in Generations |-> NoArtifact] /\ artifactBinding = [g \in Generations |-> NoArtifact]
/\ gcRequested = FALSE /\ gcRequested = FALSE
@ -75,24 +85,26 @@ BeginPrepare(p) ==
/\ materializerState[p] = "Absent" /\ materializerState[p] = "Absent"
/\ prepareIntent' = [prepareIntent EXCEPT ![p] = TRUE] /\ prepareIntent' = [prepareIntent EXCEPT ![p] = TRUE]
/\ materializerState' = [materializerState EXCEPT ![p] = "Live"] /\ materializerState' = [materializerState EXCEPT ![p] = "Live"]
/\ UNCHANGED <<artifactState, stageState, leases, mounts, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState, leases,
artifactBinding, gcRequested, replacementPresent, foreignObserved>> selectionBinding, mounts, artifactBinding, gcRequested,
replacementPresent, foreignObserved>>
CreateOwnedStage(p) == CreateOwnedStage(p) ==
/\ stageState[p] = "Absent" /\ stageState[p] = "Absent"
/\ prepareIntent[p] /\ prepareIntent[p]
/\ materializerState[p] = "Live" /\ materializerState[p] = "Live"
/\ stageState' = [stageState EXCEPT ![p] = "Owned"] /\ stageState' = [stageState EXCEPT ![p] = "Owned"]
/\ UNCHANGED <<artifactState, prepareIntent, materializerState, leases, /\ UNCHANGED <<artifactState, artifactIncarnation, prepareIntent,
mounts, artifactBinding, gcRequested, replacementPresent, materializerState, leases, selectionBinding, mounts, artifactBinding,
foreignObserved>> gcRequested, replacementPresent, foreignObserved>>
LoseMaterializer(p) == LoseMaterializer(p) ==
/\ prepareIntent[p] /\ prepareIntent[p]
/\ materializerState[p] = "Live" /\ materializerState[p] = "Live"
/\ materializerState' = [materializerState EXCEPT ![p] = "Lost"] /\ materializerState' = [materializerState EXCEPT ![p] = "Lost"]
/\ UNCHANGED <<artifactState, stageState, prepareIntent, leases, mounts, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
artifactBinding, gcRequested, replacementPresent, foreignObserved>> prepareIntent, leases, selectionBinding, mounts, artifactBinding,
gcRequested, replacementPresent, foreignObserved>>
PublishArtifact(p) == PublishArtifact(p) ==
/\ artifactState = "Absent" /\ artifactState = "Absent"
@ -100,11 +112,12 @@ PublishArtifact(p) ==
/\ prepareIntent[p] /\ prepareIntent[p]
/\ materializerState[p] = "Live" /\ materializerState[p] = "Live"
/\ artifactState' = "Published" /\ artifactState' = "Published"
/\ artifactIncarnation' = A1
/\ stageState' = [stageState EXCEPT ![p] = "Absent"] /\ stageState' = [stageState EXCEPT ![p] = "Absent"]
/\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE] /\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE]
/\ materializerState' = [materializerState EXCEPT ![p] = "Absent"] /\ materializerState' = [materializerState EXCEPT ![p] = "Absent"]
/\ UNCHANGED <<leases, mounts, artifactBinding, gcRequested, /\ UNCHANGED <<leases, selectionBinding, mounts, artifactBinding,
replacementPresent, foreignObserved>> gcRequested, replacementPresent, foreignObserved>>
ReusePublishedArtifact(p) == ReusePublishedArtifact(p) ==
/\ artifactState = "Published" /\ artifactState = "Published"
@ -115,8 +128,9 @@ ReusePublishedArtifact(p) ==
/\ stageState' = [stageState EXCEPT ![p] = "Absent"] /\ stageState' = [stageState EXCEPT ![p] = "Absent"]
/\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE] /\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE]
/\ materializerState' = [materializerState EXCEPT ![p] = "Absent"] /\ materializerState' = [materializerState EXCEPT ![p] = "Absent"]
/\ UNCHANGED <<artifactState, leases, mounts, artifactBinding, /\ UNCHANGED <<artifactState, artifactIncarnation, leases,
gcRequested, replacementPresent, foreignObserved>> selectionBinding, mounts, artifactBinding, gcRequested,
replacementPresent, foreignObserved>>
RecoverUnmaterializedIntent(p) == RecoverUnmaterializedIntent(p) ==
/\ stageState[p] = "Absent" /\ stageState[p] = "Absent"
@ -124,8 +138,9 @@ RecoverUnmaterializedIntent(p) ==
/\ materializerState[p] = "Lost" /\ materializerState[p] = "Lost"
/\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE] /\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE]
/\ materializerState' = [materializerState EXCEPT ![p] = "Absent"] /\ materializerState' = [materializerState EXCEPT ![p] = "Absent"]
/\ UNCHANGED <<artifactState, stageState, leases, mounts, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState, leases,
artifactBinding, gcRequested, replacementPresent, foreignObserved>> selectionBinding, mounts, artifactBinding, gcRequested,
replacementPresent, foreignObserved>>
RecoverOwnedStage(p) == RecoverOwnedStage(p) ==
/\ stageState[p] = "Owned" /\ stageState[p] = "Owned"
@ -134,8 +149,9 @@ RecoverOwnedStage(p) ==
/\ stageState' = [stageState EXCEPT ![p] = "Absent"] /\ stageState' = [stageState EXCEPT ![p] = "Absent"]
/\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE] /\ prepareIntent' = [prepareIntent EXCEPT ![p] = FALSE]
/\ materializerState' = [materializerState EXCEPT ![p] = "Absent"] /\ materializerState' = [materializerState EXCEPT ![p] = "Absent"]
/\ UNCHANGED <<artifactState, leases, mounts, artifactBinding, /\ UNCHANGED <<artifactState, artifactIncarnation, leases,
gcRequested, replacementPresent, foreignObserved>> selectionBinding, mounts, artifactBinding, gcRequested,
replacementPresent, foreignObserved>>
ObserveForeignStage(p) == ObserveForeignStage(p) ==
/\ stageState[p] = "Absent" /\ stageState[p] = "Absent"
@ -143,20 +159,42 @@ ObserveForeignStage(p) ==
/\ materializerState[p] = "Absent" /\ materializerState[p] = "Absent"
/\ stageState' = [stageState EXCEPT ![p] = "Foreign"] /\ stageState' = [stageState EXCEPT ![p] = "Foreign"]
/\ foreignObserved' = TRUE /\ foreignObserved' = TRUE
/\ UNCHANGED <<artifactState, prepareIntent, materializerState, leases, /\ UNCHANGED <<artifactState, artifactIncarnation, prepareIntent,
mounts, artifactBinding, gcRequested, replacementPresent>> materializerState, leases, selectionBinding, mounts, artifactBinding,
gcRequested, replacementPresent>>
RefuseForeignStage(p) == RefuseForeignStage(p) ==
/\ stageState[p] = "Foreign" /\ stageState[p] = "Foreign"
/\ UNCHANGED vars /\ UNCHANGED vars
SelectPublishedArtifact(g) ==
/\ artifactState = "Published"
/\ ~gcRequested
/\ g \notin leases
/\ selectionBinding[g] = NoArtifact
/\ selectionBinding' =
[selectionBinding EXCEPT ![g] = artifactIncarnation]
/\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
prepareIntent, materializerState, leases, mounts, artifactBinding,
gcRequested, replacementPresent, foreignObserved>>
ReleaseSelection(g) ==
/\ selectionBinding[g] # NoArtifact
/\ g \notin leases
/\ selectionBinding' = [selectionBinding EXCEPT ![g] = NoArtifact]
/\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
prepareIntent, materializerState, leases, mounts, artifactBinding,
gcRequested, replacementPresent, foreignObserved>>
AcquireLease(g) == AcquireLease(g) ==
/\ artifactState = "Published" /\ artifactState = "Published"
/\ ~gcRequested /\ ~gcRequested
/\ g \notin leases /\ g \notin leases
/\ selectionBinding[g] = artifactIncarnation
/\ leases' = leases \cup {g} /\ leases' = leases \cup {g}
/\ selectionBinding' = [selectionBinding EXCEPT ![g] = NoArtifact]
/\ artifactBinding' = [artifactBinding EXCEPT ![g] = Artifact] /\ artifactBinding' = [artifactBinding EXCEPT ![g] = Artifact]
/\ UNCHANGED <<artifactState, stageState, prepareIntent, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState, prepareIntent,
materializerState, mounts, gcRequested, replacementPresent, materializerState, mounts, gcRequested, replacementPresent,
foreignObserved>> foreignObserved>>
@ -165,54 +203,60 @@ MountStateAnchor(g) ==
/\ artifactBinding[g] = Artifact /\ artifactBinding[g] = Artifact
/\ g \notin mounts /\ g \notin mounts
/\ mounts' = mounts \cup {g} /\ mounts' = mounts \cup {g}
/\ UNCHANGED <<artifactState, stageState, prepareIntent, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
materializerState, leases, artifactBinding, gcRequested, prepareIntent, materializerState, leases, selectionBinding,
replacementPresent, foreignObserved>> artifactBinding, gcRequested, replacementPresent, foreignObserved>>
UnmountStateAnchor(g) == UnmountStateAnchor(g) ==
/\ g \in mounts /\ g \in mounts
/\ mounts' = mounts \ {g} /\ mounts' = mounts \ {g}
/\ UNCHANGED <<artifactState, stageState, prepareIntent, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
materializerState, leases, artifactBinding, gcRequested, prepareIntent, materializerState, leases, selectionBinding,
replacementPresent, foreignObserved>> artifactBinding, gcRequested, replacementPresent, foreignObserved>>
ReleaseLease(g) == ReleaseLease(g) ==
/\ g \in leases /\ g \in leases
/\ g \notin mounts /\ g \notin mounts
/\ leases' = leases \ {g} /\ leases' = leases \ {g}
/\ artifactBinding' = [artifactBinding EXCEPT ![g] = NoArtifact] /\ artifactBinding' = [artifactBinding EXCEPT ![g] = NoArtifact]
/\ UNCHANGED <<artifactState, stageState, prepareIntent, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
materializerState, mounts, gcRequested, replacementPresent, prepareIntent, materializerState, selectionBinding, mounts,
foreignObserved>> gcRequested, replacementPresent, foreignObserved>>
RequestGC == RequestGC ==
/\ artifactState = "Published" /\ artifactState = "Published"
/\ leases = {} /\ leases = {}
/\ \A g \in Generations : selectionBinding[g] = NoArtifact
/\ ~gcRequested /\ ~gcRequested
/\ gcRequested' = TRUE /\ gcRequested' = TRUE
/\ UNCHANGED <<artifactState, stageState, prepareIntent, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
materializerState, leases, mounts, artifactBinding, prepareIntent, materializerState, leases, selectionBinding, mounts,
replacementPresent, foreignObserved>> artifactBinding, replacementPresent, foreignObserved>>
PublishReplacementDuringGC == PublishReplacementDuringGC ==
/\ artifactState = "Published" /\ artifactState = "Published"
/\ gcRequested /\ gcRequested
/\ ~replacementPresent /\ ~replacementPresent
/\ replacementPresent' = TRUE /\ replacementPresent' = TRUE
/\ UNCHANGED <<artifactState, stageState, prepareIntent, /\ UNCHANGED <<artifactState, artifactIncarnation, stageState,
materializerState, leases, mounts, artifactBinding, gcRequested, prepareIntent, materializerState, leases, selectionBinding, mounts,
foreignObserved>> artifactBinding, gcRequested, foreignObserved>>
ReclaimArtifact == ReclaimArtifact ==
/\ artifactState = "Published" /\ artifactState = "Published"
/\ gcRequested /\ gcRequested
/\ leases = {} /\ leases = {}
/\ \A g \in Generations : selectionBinding[g] = NoArtifact
/\ mounts = {} /\ mounts = {}
/\ artifactState' = IF replacementPresent THEN "Published" ELSE "Absent" /\ artifactState' = IF replacementPresent THEN "Published" ELSE "Absent"
/\ artifactIncarnation' =
IF replacementPresent
THEN IF artifactIncarnation = A1 THEN A2 ELSE A1
ELSE NoArtifact
/\ gcRequested' = FALSE /\ gcRequested' = FALSE
/\ replacementPresent' = FALSE /\ replacementPresent' = FALSE
/\ UNCHANGED <<stageState, prepareIntent, materializerState, leases, /\ UNCHANGED <<stageState, prepareIntent, materializerState, leases,
mounts, artifactBinding, foreignObserved>> selectionBinding, mounts, artifactBinding, foreignObserved>>
Next == Next ==
\/ (\E p \in Preparations : BeginPrepare(p)) \/ (\E p \in Preparations : BeginPrepare(p))
@ -224,6 +268,8 @@ Next ==
\/ (\E p \in Preparations : RecoverOwnedStage(p)) \/ (\E p \in Preparations : RecoverOwnedStage(p))
\/ (\E p \in Preparations : ObserveForeignStage(p)) \/ (\E p \in Preparations : ObserveForeignStage(p))
\/ (\E p \in Preparations : RefuseForeignStage(p)) \/ (\E p \in Preparations : RefuseForeignStage(p))
\/ (\E g \in Generations : SelectPublishedArtifact(g))
\/ (\E g \in Generations : ReleaseSelection(g))
\/ (\E g \in Generations : AcquireLease(g)) \/ (\E g \in Generations : AcquireLease(g))
\/ (\E g \in Generations : MountStateAnchor(g)) \/ (\E g \in Generations : MountStateAnchor(g))
\/ (\E g \in Generations : UnmountStateAnchor(g)) \/ (\E g \in Generations : UnmountStateAnchor(g))
@ -236,10 +282,13 @@ Spec == Init /\ [][Next]_vars
TypeOK == TypeOK ==
/\ artifactState \in ArtifactStates /\ artifactState \in ArtifactStates
/\ artifactIncarnation \in ArtifactIncarnations \cup {NoArtifact}
/\ stageState \in [Preparations -> StageStates] /\ stageState \in [Preparations -> StageStates]
/\ prepareIntent \in [Preparations -> BOOLEAN] /\ prepareIntent \in [Preparations -> BOOLEAN]
/\ materializerState \in [Preparations -> MaterializerStates] /\ materializerState \in [Preparations -> MaterializerStates]
/\ leases \subseteq Generations /\ leases \subseteq Generations
/\ selectionBinding \in
[Generations -> ArtifactIncarnations \cup {NoArtifact}]
/\ mounts \subseteq Generations /\ mounts \subseteq Generations
/\ artifactBinding \in [Generations -> {NoArtifact, Artifact}] /\ artifactBinding \in [Generations -> {NoArtifact, Artifact}]
/\ gcRequested \in BOOLEAN /\ gcRequested \in BOOLEAN
@ -254,6 +303,16 @@ PrepareOwnershipConsistent ==
/\ ~prepareIntent[p] /\ ~prepareIntent[p]
/\ materializerState[p] = "Absent" /\ materializerState[p] = "Absent"
ArtifactIncarnationConsistent ==
(artifactState = "Absent") <=> (artifactIncarnation = NoArtifact)
SelectionBindingConsistent ==
\A g \in Generations :
selectionBinding[g] # NoArtifact =>
/\ artifactState = "Published"
/\ selectionBinding[g] = artifactIncarnation
/\ g \notin leases
LiveOwnedStageNotRecoverable == LiveOwnedStageNotRecoverable ==
\A p \in Preparations : \A p \in Preparations :
materializerState[p] = "Live" => ~ENABLED RecoverOwnedStage(p) materializerState[p] = "Live" => ~ENABLED RecoverOwnedStage(p)
@ -295,6 +354,16 @@ GCExcludesLeases ==
/\ leases = {} /\ leases = {}
/\ mounts = {} /\ mounts = {}
GCExcludesSelections ==
gcRequested =>
\A g \in Generations : selectionBinding[g] = NoArtifact
SelectedArtifactStable ==
\A g \in Generations :
selectionBinding[g] # NoArtifact =>
/\ ~ENABLED RequestGC
/\ ~ENABLED ReclaimArtifact
ReplacementOnlyDuringGC == ReplacementOnlyDuringGC ==
replacementPresent => gcRequested replacementPresent => gcRequested