1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package day
import (
"fmt"
"strings"
)
// Change describes one slot transition for the confirmation table.
type Change struct {
Index int
FromID *string // nil = was empty
ToID *string // nil = cleared
}
// ResolveLog computes the write set for a log command. activityID nil means
// plan-fill: every target slot takes its plan block's activity, and any slot
// without one aborts the whole command (all-or-nothing).
func ResolveLog(targets []int, activityID *string, blocks, planBlocks map[int]string, blockSize int) (map[int]*string, []Change, error) {
assignments := make(map[int]*string, len(targets))
var overwrites []Change
if activityID == nil {
var missing []string
for _, i := range targets {
if _, ok := planBlocks[i]; !ok {
missing = append(missing, SlotLabel(i, blockSize))
}
}
if len(missing) > 0 {
return nil, nil, fmt.Errorf("no planned activity at %s โ nothing painted", strings.Join(missing, ", "))
}
}
for _, i := range targets {
to := activityID
if to == nil {
v := planBlocks[i]
to = &v
}
assignments[i] = to
if from, ok := blocks[i]; ok && from != *to {
f := from
overwrites = append(overwrites, Change{Index: i, FromID: &f, ToID: to})
}
}
return assignments, overwrites, nil
}
// ResolveClear computes the write set for a clear command. Only slots that
// are actually logged are touched; clearing an empty slot is a no-op.
func ResolveClear(targets []int, blocks map[int]string) (map[int]*string, []Change) {
assignments := make(map[int]*string)
var cleared []Change
for _, i := range targets {
if from, ok := blocks[i]; ok {
f := from
assignments[i] = nil
cleared = append(cleared, Change{Index: i, FromID: &f, ToID: nil})
}
}
return assignments, cleared
}
|